我是靠谱客的博主 糟糕西装,最近开发中收集的这篇文章主要介绍hdu5794A Simple Chess(组合数学),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5794

题目大意:

给一个n*m的棋盘,要求从(1,1)走到(n,m),只能以日字的形式走过去,然后不能经过某些坏点,问有几种走法。

范围:

n,m<=10^18,mod=110119。

思路:

和上一题的模型很相似。具体见http://blog.csdn.net/aaaaacmer/article/details/52132704。

但是要进行转化。转换方式比较神奇,就是先将x,y坐标都减1,然后将X=-1/3x+2/3y,Y=2/3x-1/3y。转化以后可以知道,如果新的坐标不为非负整数,就是不可到达的点,然后利用模型直接计算。因为n,m比较大,而mod比较小,所以可以用卢卡斯定理解决。

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#define eps 0.001
#define mod 110119
#define ll __int64
using namespace std;
ll f[200];
struct node{
	ll x,y;
}p[200];

bool cmp(node a,node b){
	if(a.x!=b.x)return a.x<b.x;
	return a.y<b.y;
}
ll PowMod(ll a,ll b,ll MOD){    
    ll ret=1;    
    while(b){    
        if(b&1) ret=(ret*a)%MOD;    
        a=(a*a)%MOD;    
        b>>=1;    
    }    
    return ret;    
}    
ll fac[110121];    
ll Get_Fact(ll p){    
    fac[0]=1;    
    for(ll i=1;i<=p;i++)    
        fac[i]=(fac[i-1]*i)%p;  //预处理阶乘   
}    
ll Lucas(ll n,ll m,ll p){    
    ll ret=1;    
    while(n&&m){    
        ll a=n%p,b=m%p;    
        if(a<b) return 0;    
        ret=(ret*fac[a]*PowMod(fac[b]*fac[a-b]%p,p-2,p))%p;    
        n/=p;    
        m/=p;    
    }    
    return ret;    
}
int main()
{
	ll n,m;
	int i,j,k,r,tt;
	int icase=0;
	Get_Fact(mod);
	while(~scanf("%I64d%I64d%d",&n,&m,&r)){
		icase++;
		tt=0;
		ll xx,yy;
		for(i=1;i<=r;i++){
			scanf("%I64d%I64d",&xx,&yy);
			xx--;
			yy--;
			ll x,y;
			x=-xx+2*yy;
			y=2*xx-1*yy;
			if(x%3==0&&y%3==0&&x>=0&&y>=0){
				p[++tt].x=x/3;
				p[tt].y=y/3;
			}
		}
		printf("Case #%d: ",icase);
		ll edx,edy;
		edx=-(n-1)+2*(m-1);
		edy=2*(n-1)-1*(m-1);
		if(!(edx%3==0&&edy%3==0&&edx>=0&&edy>=0)){
			printf("0n");
			continue;
		}
		sort(p+1,p+1+tt,cmp);
		memset(f,0,sizeof(f));
		p[tt+1].x=edx/3;
		p[tt+1].y=edy/3;
		for(i=1;i<=tt+1;i++){
			ll dx,dy;
			dx=p[i].x;
			dy=p[i].y;
			ll tmp=Lucas(dx+dy,dx,mod);
			for(j=1;j<i;j++){
				if(p[i].x>=p[j].x&&p[i].y>=p[j].y){
					ll dxx,dyy;
					dxx=p[i].x-p[j].x;
					dyy=p[i].y-p[j].y;
					tmp-=f[j]*Lucas(dxx+dyy,dxx,mod)%mod;
					tmp=(tmp+mod)%mod;		
				}
			
			}	
			f[i]=(tmp+mod)%mod;
		}
		printf("%I64dn",(f[tt+1]+mod)%mod);
	}	
}



最后

以上就是糟糕西装为你收集整理的hdu5794A Simple Chess(组合数学)的全部内容,希望文章能够帮你解决hdu5794A Simple Chess(组合数学)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部