zoukankan      html  css  js  c++  java
  • [HDU5794]A Simple Chess

    Description
    There is a (n×m) board, a chess want to go to the position ((n,m)) from the position ((1,1)).
    The chess is able to go to position ((x_2,y_2)) from the position ((x_1,y_1)), only and if only (x_1,y_1,x_2,y_2) is satisfied that ((x_2−x_1)^2+(y_2−y_1)^2=5, x_2>x_1, y_2>y_1).
    Unfortunately, there are some obstacles on the board. And the chess never can stay on the grid where has a obstacle.
    I want you to tell me, There are how may ways the chess can achieve its goal.

    Input
    The input consists of multiple test cases.
    For each test case:
    The first line is three integers, (n,m,r,(1leqslant n,mleqslant 10^{18},0leqslant rleqslant100)), denoting the height of the board, the weight of the board, and the number of the obstacles on the board.
    Then follow (r) lines, each lines have two integers, (x,y(1leqslant xleqslant n,1leqslant yleqslant m)), denoting the position of the obstacles. please note there aren't never a obstacles at position ((1,1)).

    Output
    For each test case,output a single line "Case #x: y", where x is the case number, starting from 1. And y is the answer after module 110119.

    Sample Input

    1 1 0
    3 3 0
    4 4 1
    2 1
    4 4 1
    3 2
    7 10 2
    1 2
    7 1
    

    Sample Output

    Case #1: 1
    Case #2: 0
    Case #3: 2
    Case #4: 1
    Case #5: 5
    

    尽管本题是走日字,但由于每次必须向坐标更大的地方跳,故实际上和普通的走法无较大区别,需要注意的一点是要判断一个点是否能通过跳日字到达另一个点

    对于障碍点的计算,记(A)到终点的所有路径数为(S_A),记(T_A)(A)出发不经过任何障碍点到达终点的路径数,则有(T_A=S_A-sumlimits_{A<B}T_B),其中(B)为障碍点,(A<B)表示(A)的坐标严格小于(B),即(A)可以通过某些方式跳到(B)

    我们将起点(O)也加入障碍点,最后算出的(T_O)即为答案

    注意在计算的时候,组合数会非常大,因此需要用到Lucas定理:(inom{n}{m}equivinom{n\%p}{m\%p}inom{n/p}{m/p} \% p)

    /*program from Wolfycz*/
    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define Fi first
    #define Se second
    #define ll_inf 1e18
    #define MK make_pair
    #define sqr(x) ((x)*(x))
    #define pii pair<int,int>
    #define int_inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>inline T frd(T x){
    	int f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    template<typename T>inline T read(T x){
    	int f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e3,P=110119;
    struct node{
    	ll x,y;
    	node(ll _x=0,ll _y=0){x=_x,y=_y;}
    	void clear(){x=y=0;}
    	void insert(ll _x,ll _y){x=_x,y=_y;}
    	void print(){printf("%lld %lld
    ",x,y);}
    	bool operator <(const node &tis)const{return x!=tis.x?x<tis.x:y<tis.y;}
    	bool operator ==(const node &tis)const{return x==tis.x&&y==tis.y;}
    }Obstacles[N+10];
    int fac[P+10],inv[P+10];
    int C(ll n,ll m){
    	if (n<m)	return 0;
    	if (n<P&&m<P)	return 1ll*fac[n]*inv[m]%P*inv[n-m]%P;
    	return 1ll*C(n/P,m/P)*C(n%P,m%P)%P;
    }
    void prepare(){
    	fac[0]=inv[0]=inv[1]=1;
    	for (int i=1;i<P;i++)	fac[i]=1ll*i*fac[i-1]%P;
    	for (int i=2;i<P;i++)	inv[i]=1ll*(P-P/i)*inv[P%i]%P;
    	for (int i=1;i<P;i++)	inv[i]=1ll*inv[i-1]*inv[i]%P;
    }
    int solve(ll x,ll y){
    	ll delta=abs(x-y),cnt=(min(x,y)-delta)/3;
    	return C((cnt<<1)+delta,cnt);
    }
    bool Check(ll x,ll y){
    	ll delta=abs(x-y);
    	if (min(x,y)<delta)	return 0;
    	if ((min(x,y)-delta)%3)	return 0;
    	return 1;
    }
    int Ans[N+10];
    void init(){
    	memset(Ans,0,sizeof(Ans));
    	for (int i=0;i<=N;i++)	Obstacles[i].clear();
    }
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	prepare();
    	ll n,m; int r,Case=0;
    	while (scanf("%lld%lld%d",&n,&m,&r)!=EOF){
    		int cnt=0; bool Flag=0;
    		n--,m--; init();
    		for (int i=1;i<=r;i++){
    			ll x=read(0ll)-1,y=read(0ll)-1;
    			if (x==n&&y==m)	Flag|=1;
    			if (!Check(x,y))	continue;
    			Obstacles[++cnt].insert(x,y);
    		}
    		Obstacles[++cnt].insert(n,m);
    		if (!Check(n,m)||Flag){
    			printf("Case #%d: 0
    ",++Case);
    			continue;
    		}
    		sort(Obstacles+1,Obstacles+1+cnt);
    		for (int i=1;i<=cnt;i++){
    			Ans[i]=solve(Obstacles[i].x,Obstacles[i].y);
    			for (int j=1;j<i;j++){
    				if (Obstacles[j]<Obstacles[i]){
    					ll X_i=Obstacles[i].x,Y_i=Obstacles[i].y;
    					ll X_j=Obstacles[j].x,Y_j=Obstacles[j].y;
    					if (!Check(X_i-X_j,Y_i-Y_j))	continue;
    					Ans[i]=(Ans[i]-1ll*Ans[j]*solve(X_i-X_j,Y_i-Y_j)%P)%P;
    				}else	break;
    			}
    			Ans[i]=(Ans[i]+P)%P;
    		}
    		printf("Case #%d: %d
    ",++Case,Ans[cnt]);
    	}
    	return 0;
    }
    
    作者:Wolfycz
    本文版权归作者和博客园共有,欢迎转载,但必须在文章开头注明原文出处,否则保留追究法律责任的权利
  • 相关阅读:
    【面霸2】
    【面霸1】php知识点
    【技术宅11】php入门运算
    【技术宅10】顺序二分查找算法
    【技术宅9】遍历一个文件夹下的所有文件和子文件夹
    【技术宅7】一个或多个虚拟主机配置方法
    【技术宅6】把一个无限级分类循环成tree结构
    【技术宅5】抓去网页数据的3种方法
    【技术宅4】如何把M个苹果平均分给N个小朋友
    【技术宅3】截取文件和url扩展名的N种方法
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/14931534.html
Copyright © 2011-2022 走看看