CF#313-E. Gerald and Giant Chess-dp+组合数学

来源:互联网 发布:朝阳区群众 知乎 编辑:程序博客网 时间:2024/05/30 04:32

一开始想用容斥原理 。。后来发现有些地方处理有些麻烦。。。


用dp的话,dp[i]并表示 从起点到 障碍i 所有的合法路径数

hint: 从起点到点 x,y的所有路径方案为  C(x-1+y-1,x-1) (要减一是因为本题是格点)


那么 对点i,把所有在点i的左上方的点称为j

dp[i]= C(x-1+y-1,x-1);

对所有j点:dp[i]-=dp[j]*get_dis(i,j) 

把第q+1个点设为(n,m)即可


取组合要用到费马小定理,预处理好阶乘




#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <cmath>using namespace std;__int64 dp[2005] ;__int64 mod=1e9+7;__int64 fast_m(__int64 a,__int64 b)  {      __int64 x,ans=1;      x=a;      while(b)      {          if (b&1)              ans=(ans*x)%mod;          x=(x*x)%mod;          b/=2;      }      return ans;  } __int64 fac[200010];  inline __int64 cal(__int64 x,__int64 y)  {       return (fac[x]*fast_m(fac[y]*fac[x-y]%mod,mod-2))%mod;   } struct node{__int64 x,y;};node tm[2005];bool cmp(node &a,node &b){if (a.x!=b.x)return a.x<b.x;elsereturn a.y<b.y;} int main(){__int64 x,y,i,j;__int64 n,m,q;scanf("%I64d%I64d%I64d",&n,&m,&q);    fac[0]=1;  for(  i=1;i<=2e5;i++)    fac[i]=fac[i-1]*i%mod;   for (i=1;i<=q;i++){scanf("%I64d%I64d",&tm[i].x,&tm[i].y); } sort(tm+1,tm+1+q,cmp);tm[q+1].x=n;tm[q+1].y=m;__int64 add=0;for (i=1;i<=q+1;i++){dp[i]=cal(tm[i].x+tm[i].y-2,tm[i].x-1);for (j=1;j<i;j++){if (tm[j].x<=tm[i].x&&tm[j].y<=tm[i].y){dp[i]= dp[i]-cal(tm[i].x+tm[i].y-tm[j].x-tm[j].y,tm[i].y-tm[j].y)*(dp[j])   %mod; dp[i]=(dp[i]+mod)%mod;}}}__int64 ans=dp[q+1];while(ans<0) ans+=mod;printf("%I64d\n",(ans) %mod);return 0;}



0 0
原创粉丝点击