HDU 5794 A Simple Chess (容斥+Lucas定理)
2016-08-05 17:17
561 查看
A Simple Chess
题目链接:点我打开链接[align=left]Author[/align]
UESTC
[align=left]Source[/align]
2016 Multi-University Training Contest 6
题意:规定起始点(1,1),要求到达(n,m),下一步(x2,y2),这一步(x1,y1),并且这两点坐标要求满足(x2-x1)^2 +(y2-y1)^2
= 5,且 x2>x1 、y2>y1。中间有 r 个障碍点,问最终有多少种方法到达(n,m)。
题解:你大概画个图嘛。
(画得有点丑。。。)
可以看出不存在障碍物时棋子走法是一个斜着的杨辉三角。由于每次棋子移动的横纵坐标差值和一定是3,所以棋子所在的层数n等于(x+y)/3。棋子从(1,1)点开始移动,只有满足(x+y)%3==2
&& x>=n+1 && y>=n+1的点棋子才能到达。可以先计算出(1,1)到每个障碍点的方法数(先当做这个障碍点不受其他障碍点影响,即不管这个障碍点的前面是否又有障碍点),然后对障碍点排序,然后两重循环,判断这个障碍点p1会对哪些障碍点(和终点(终点也可能有障碍物))p2照成影响,受影响的障碍点减去影响数,就可以计算剩下的方法就是答案了。由于棋盘界限很大,但取模数为110119,也满足Lucas定理的要求,可以利用Lucas定理快速求大组合数取模的结果。
出题人题解:点我打开链接 Orz....
AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; const long long mod=110119; LL all[mod+10],f[mod+10]; LL dp[2010]; struct node { LL x,y; } point[2010]; LL cmp(node a,node b) { return a.x<b.x; } void init() { f[1]=f[0]=all[1]=1; for(int i=2; i<=mod; ++i) { f[i]=f[i-1]*i%mod; all[i]=all[mod%i]*(mod-mod/i)%mod; } } LL C(LL n, LL m) { if(m > n) return 0; if (m==0) return 1; if (m<0) return 0; return f *all[f[m]]%mod*all[f[n-m]]%mod; } LL Lucas(LL n, LL m) { if(m == 0) return 1; return C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod; } int main() { init(); LL h,w,n,cas=1; while (scanf ("%lld%lld%lld",&h,&w,&n)!=EOF) { int flag=0; memset(dp,0,sizeof(dp)); LL t1,t2; for (int i=0; i<n; ++i) { scanf ("%lld%lld",&t1,&t2); if (t1==h&&t2==w) flag=1; point[i].x=t1-1; point[i].y=t2-1; } sort(point,point+n,cmp); point .x=h-1; point .y=w-1; ++n; if ((point[n-1].x+point[n-1].y)%3!=0||flag) { //printf("n=%lld\n",n); //printf("dp[0]=%lld\n",dp[0]); printf ("Case #%lld: %d\n",cas++, 0); continue; } for (int i=0; i<n; i++) { if ((point[i].x+point[i].y)%3==0) { LL low=(point[i].x+point[i].y)/3; LL high=min(point[i].x,point[i].y)-low; dp[i]=Lucas(low,high); for (int j=0;j<i;j++) { if (point[j].y<point[i].y&&point[j].x<point[i].x) { LL xx=point[i].x-point[j].x,yy=point[i].y-point[j].y; if ((xx+yy)%3==0) { LL dd=(xx+yy)/3; LL gg=min(xx,yy)-dd; dp[i]-=(Lucas(dd,gg)*dp[j])%mod; dp[i]=(dp[i]+mod)%mod; } } } } } //printf("n=%lld\n",n); //printf("dp[0]=%lld\n",dp[0]); printf ("Case #%lld: %lld\n",cas++,dp[n-1]); } return 0; }
相关文章推荐
- HDU 5794 A Simple Chess (容斥+lucas定理)
- HDU 5794 A Simple Chess (lucas定理+费马小定理)
- HDU 5794 A Simple Chess (容斥原理+Lucas定理+dp)
- HDU_5794_ASimpleChess(Lucas定理&&(容斥||dp))
- hdu 5794 A Simple Chess(Lucas 定理)
- HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)
- HDU-5794 <2016 Multi-University Training 6> A Simple Chess (Lucas + DP)
- HDU 5794 A Simple Chess 16多校6 dp 容斥 lucas
- HDU 5794 A Simple Chess (容斥+DP+Lucas)
- HDU 5794 A Simple Chess (Lucas + dp)
- HDU 5794 A Simple Chess dp+Lucas
- 【HDOJ 5794】A Simple Chess(大组合数Lucas定理+容斥)
- (HDU 5794)2016 Multi-University Training Contest 6 A Simple Chess (Lucas、容斥)
- HDU 5794 A Simple Chess Lucas大数组合数取模
- HDU5794 A Simple Chess (容斥+卢卡斯)
- hdu 5794 A Simple Chess 【lucas+容斥】
- HDU 5794 A Simple Chess (dp+Lucas组合数取模)
- hdu_5794_A Simple Chess(lucas+dp)
- hdu 6114 Chess(组合数取模)(Lucas定理)
- hdu 6114 Chess(组合数取模)(Lucas定理)