标签:
1 1 0
3 3 0
4 4 1
2 1
4 4 1
3 2
7 10 2
1 2
7 1
Case #1: 1
Case #2: 0
Case #3: 2
Case #4: 1
Case #5: 5
题目大意:
给一个
解题思路:
卢卡斯定理加上容斥,
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
typedef long long LL;
const LL MOD = 110119LL;
struct Node
{
LL x, y, s;
} node[105];
int cmp(const Node s1,const Node s2)
{
if(s1.x==s2.x)
return s1.y<s2.y;
return s1.x<s2.x;
}
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[1000005];
void 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;
int Case=1;
Get_Fact(MOD);
while(scanf("%lld%lld%d",&n,&m,&r)!=EOF)
{
int tot=0;
LL sum=0;
int flag=0;
if((n+m+1)%3==0)
{
LL s=(n+m+1)/3;
if(n>=s&&m>=s)
{
LL t=n;
n=2*s-m;
m=2*s-t;
}
else
{
flag=1;
}
}
else
{
flag=1;
}
for(int i=0; i<r; i++)
{
LL x,y;
scanf("%lld%lld",&x,&y);
if((x+y+1)%3==0)
{
LL s=(x+y+1)/3;
if(x>=s&&y>=s)
{
node[tot].x=2*s-y;
node[tot].y=2*s-x;
if(node[tot].x<=n&&node[tot].y<=m)
tot++;
}
}
}
if(flag==1)
{
printf("Case #%d: %lld\n",Case++,sum);
continue;
}
if(tot>0)
sort(node,node+tot,cmp);
sum=Lucas(n+m-2,n-1,MOD)%MOD;
for(int i=0; i<tot; i++)
{
node[i].s=Lucas(node[i].x+node[i].y-2,node[i].x-1,MOD)%MOD;
}
for(int i=0; i<tot; i++)
{
LL tt=Lucas(n-node[i].x+m-node[i].y,m-node[i].y,MOD);
for(int j=i+1; j<tot; j++)
{
if(node[j].y>=node[i].y)
{
LL d1=node[j].y-node[i].y;
LL d2=node[j].x-node[i].x;
node[j].s=(node[j].s-(node[i].s*Lucas(d1+d2,d1,MOD))%MOD)%MOD;
}
}
sum=(sum-(node[i].s*tt)%MOD)%MOD;
sum = (sum%MOD+MOD)%MOD;
}
printf("Case #%d: %lld\n",Case++,sum);
}
}
HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)
标签:
原文地址:http://blog.csdn.net/qingshui23/article/details/52127322