A Simple Chess
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 87 Accepted Submission(s): 15
Total Submission(s): 87 Accepted Submission(s): 15
Problem 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 (x2,y2) from the position (x1,y1) , only and if only x1,y1,x2,y2 is satisfied that (x2−x1)2+(y2−y1)2=5, x2>x1, y2>y1 .
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.
(n,m) from the position (1,1) .
The chess is able to go to position (x2,y2) from the position (x1,y1) , only and if only x1,y1,x2,y2 is satisfied that (x2−x1)2+(y2−y1)2=5, x2>x1, y2>y1 .
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,(1≤n,m≤1018,0≤r≤100) , 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(1≤x≤n,1≤y≤m) , denoting the position of the obstacles. please note there aren't never a obstacles at position (1,1) .
For each test case:
The first line is three integers, n,m,r,(1≤n,m≤1018,0≤r≤100) , 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(1≤x≤n,1≤y≤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
题意: 题目意思抽象出来就是一个n*m的矩阵,你从左上走到右下有多少种方式,只能走日字型,走的格子必须是右下方,而且规定一些方格是不能走的。
思路:如果不考虑不能走的方格,稍微自己化个图就能很清楚的发现规律;
定义最左上点为(0,0);
可知,只有格点横纵坐标和为3的倍数的某些点才能够到达。
相同横纵坐标和的格点的方案数是按照排列数的值分布的。
这个规律找出来之后就相对好做了。
有些点是不能走的。
那就计算这些点对到达末点的贡献度,减去就好了。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=110119;
struct node
{
ll x,y,w;
bool operator<(const node&p)const
{
if(x!=p.x)
return x<p.x;
return y<p.y;
}
}A[111];
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[110219];
ll Get_Fact(ll p)
{
fac[0]=1;
for(int 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 r,t=0;
Get_Fact(mod);
while(scanf("%I64d%I64d%d",&n,&m,&r)!=EOF)
{
n--,m--;
int len=0;
for(int i=0;i<r;i++)
{
ll a,b;
scanf("%I64d%I64d",&a,&b);
a--;
b--;
if((a+b)%3)
continue;
ll cc=a+b;
cc/=3;
if(b<cc||b>cc*2+1)
continue;
A[len].x=a;A[len].y=b;A[len].w=0;
len++;
}
sort(A,A+len);
ll cc=n+m;
if(cc%3||m<cc/3||m>cc/3*2+1)
{
printf("Case #%d: 0\n",++t);
continue;
}
cc/=3;
ll ans=Lucas(cc,m-cc,mod);
for(int i=0;i<len;i++)
{
ll x=A[i].x,y=A[i].y;
cc=x+y;
if(cc%3||y<cc/3||y>cc/3*2+1)
continue;
cc/=3;
ll res=Lucas(cc,y-cc,mod);
A[i].w=res;
}
for(int i=0;i<len;i++)
{
for(int j=i+1;j<len;j++)
{
ll x=A[j].x-A[i].x,y=A[j].y-A[i].y;
cc=x+y;
if(cc%3||y<cc/3||y>cc/3*2+1)
continue;
cc/=3;
ll res=Lucas(cc,y-cc,mod);
A[j].w-=A[i].w*res%mod;
A[j].w=(A[j].w%mod+mod)%mod;
}
ll x=n-A[i].x,y=m-A[i].y;
cc=x+y;
if(cc%3||y<cc/3||y>cc/3*2+1)
continue;
cc/=3;
ll res=Lucas(cc,y-cc,mod);
ans-=res*A[i].w%mod;
ans=(ans%mod+mod)%mod;
}
printf("Case #%d: %I64d\n",++t,ans);
}
return 0;
}