HDU 5794 A Simple Chess (容斥原理+Lucas定理+dp)
2018-03-08 19:11
543 查看
A Simple Chess
问题描述有一个n*m棋盘,一枚棋子要从(1,1)格子移动到(n,m)格子。
该棋子能从坐标为(x1,y1)的格子跳到格子(x2,y2),当且仅当:
(x2-x1)^2+(y2-y1)^2=5 x2>x1,y2>y1
棋盘上有r个格子有障碍物,棋子不能落到有障碍物的格子上。
请你计算,该棋子从起点到达终点总共有多少种方案。
输入格式
有若干组数据(<=25组),对于每组数据,格式如下:
一行,三个整数n,m,r
接下来r行,每行两个整数,表示一个有障碍物的格子的坐标。
<
4000
strong>输出格式[/b]
对于每组数据,输出一行,一个整数,表示所求方案数。mod 110119
样例输入 1
1 1 0
3 3 0
4 4 1
2 1
4 4 1
3 2
7 10 2
1 2
7 1
样例输出 1
1
0
2
1
5
样例输入 2
58939239 79926962 4
28255565 36535194
51497377 67322260
48931736 62290476
23383627 30097072
样例输出 2
9061
提示
对于100%的数据:1≤n,m≤10^18 , 0≤r≤100
(1,1)格子不会有障碍。
为了方便,将题目中的x,yx,y坐标都减一,变成从(0,0)(0,0)到(n−1,m−1)(n−1,m−1)
如果不考虑障碍,那么从(0,0)(0,0)到(x,y)(x,y)的方案数是一个组合数,这个比较好推,就是C2x−y3x+y3Cx+y32x−y3,注意到(x,y)(x,y)可以到达当且仅当x+y≡0 mod 3x+y≡0 mod 3
障碍数比较小,考虑容斥,令F[i]F[i]表示从(1,1)(1,1)出发,经过的第一个障碍是第ii个障碍,那么对于每一个在ii左下角的障碍jj,F[i]=C2xi−yi3xi+yi3−∑jF[j]×C2tx−ty3tx+ty3,tx=xi−xj,ty=yi−yjF[i]=Cxi+yi32xi−yi3−∑jF[j]×Ctx+ty32tx−ty3,tx=xi−xj,ty=yi−yj
直接写个记忆化搜索,暴力枚举那些点在左下方就行了。
组合数用LucasLucas处理,预处理阶乘和逆元,注意到2x−y2x−y可能小于00,此时也意味着走不到,因此要返回00
另外还需要注意如果终点是障碍,那么答案也是00
总时间复杂度O(n2×???)O(n2×???),还是很快。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> #define N 105 #define ll long long using namespace std; const ll mod=110119; ll n,m,r,F ,X ,Y ,fac[110220],inv[110220]; bool mark ; ll C(ll a,ll b) { if(a<b)return 0; return fac[a]*inv[b]%mod*inv[a-b]%mod; } ll Lucas(ll a,ll b) { if(a<b)return 0; if(a<0||b<0)return 0; if(b==0||a==0)return 1; return Lucas(a/mod,b/mod)*C(a%mod,b%mod)%mod; } ll DP(ll p) { ll i,j; if(F[p]!=-1)return F[p]; if(mark[p])return F[p]=0; F[p]=Lucas((X[p]+Y[p])/3,(2*Y[p]-X[p])/3); for(i=1;i<=r;i++) if(X[i]<X[p]&&Y[i]<Y[p]) { if(mark[i])continue; F[p]-=DP(i)*Lucas((X[p]+Y[p]-X[i]-Y[i])/3,(2*(Y[p]-Y[i])-X[p]+X[i])/3)%mod; F[p]%=mod; } F[p]+=mod;F[p]%=mod; return F[p]; } int main() { ll i,j,k,x,y;bool f; fac[0]=fac[1]=inv[0]=inv[1]=1; for(i=2;i<=mod;i++) { fac[i]=fac[i-1]*i%mod; inv[i]=(mod-mod/i)*inv[mod%i]%mod; } for(i=2;i<=mod;i++)inv[i]=inv[i]*inv[i-1]%mod; while(scanf("%lld%lld%lld",&n,&m,&r)!=EOF) { f=0; for(i=1;i<=r;i++) { scanf("%lld%lld",&X[i],&Y[i]); if(X[i]==n&&Y[i]==m)f=1; } if(f){puts("0");continue;} for(i=1;i<=r;i++)X[i]--,Y[i]--; X[++r]=n-1;Y[r]=m-1; for(i=1;i<=r;i++)mark[i]=(X[i]+Y[i])%3!=0; memset(F,-1,sizeof(F)); printf("%lld\n",DP(r)); } }
相关文章推荐
- HDU_5794_ASimpleChess(Lucas定理&&(容斥||dp))
- HDU 5794 A Simple Chess 16多校6 dp 容斥 lucas
- HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)
- HDU 5794 A Simple Chess (Lucas + dp)
- HDU 5794 A Simple Chess (dp+Lucas组合数取模)
- HDU-5794 <2016 Multi-University Training 6> A Simple Chess (Lucas + DP)
- HDU 5794 A Simple Chess dp+Lucas
- HDU 5794 A Simple Chess (容斥+Lucas定理)
- HDU 5794 A Simple Chess (lucas定理+费马小定理)
- hdu 5794 A Simple Chess(Lucas 定理)
- hdu_5794_A Simple Chess(lucas+dp)
- HDU 5794 A Simple Chess (容斥+lucas定理)
- HDU 5794-B - A Simple Chess - DP
- HDU 5794 A Simple Chess (容斥+DP+Lucas)
- 【HDOJ 5794】A Simple Chess(大组合数Lucas定理+容斥)
- HDU 5794 A Simple Chess Lucas大数组合数取模
- hdu 5794 A Simple Chess 【lucas+容斥】
- HDU 5794 A Simple Chess(多校,dp,容斥)
- (HDU 5794)2016 Multi-University Training Contest 6 A Simple Chess (Lucas、容斥)
- DP? HDU - 3944 Lucas定理+费马小定理