[ACG001E] BBQ hard [dp]

题面:

传送门

思路:

首先,一个暴力的想法

对于每一对pack,求出f(ai+aj,bi+bj),其中f(x,y)=(x+y)!/(x!y!),也就是x个a,y个b的排列方式个数

然后转化模型,将f数组变化成这样的形式:f(x,y)表示一个x行y列的方格图,左下走到右上的方法数

然后将所有的f放到一个图中,就变成了:左下的n个点(-ai,-bi)到右上的n个点(ai,bi)的总方法数(任意一个出发任意一个到达)

用DAGdp把这个方法数求出来,就是sigma(f(ai+aj,bi+bj))(i=1...n,j=1...n),减去所有的f(ai+ai,bi+bi)再除以二即可

注意:MOD1e9+7意义下,要使用乘法逆元

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 #define MOD 1000000007
 7 using namespace std;
 8 inline int read(){
 9     int re=0,flag=1;char ch=getchar();
10     while(ch>'9'||ch<'0'){
11         if(ch=='-') flag=-1;
12         ch=getchar();
13     }
14     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
15     return re*flag;
16 }
17 const int dx[3]={0,0,1},dy[3]={0,1,0};
18 ll dp[4020][4020];int N=2005;bool vis[4020][4020];
19 int n,xx[200010],yy[200010],qx[200010],qy[200010],head=0,tail=1,maxq=200000;
20 ll inv[8010],finv[8010],f[8010];
21 void init(){
22     int i;inv[1]=finv[1]=1;
23     for(i=2;i<=8000;i++){
24         inv[i]=((MOD-MOD/i)*inv[MOD%i])%MOD;
25     }
26     f[1]=1;
27     for(i=2;i<=8000;i++){
28         f[i]=(f[i-1]*i)%MOD;
29         finv[i]=(finv[i-1]*inv[i])%MOD;
30     }
31 }
32 int main(){
33     init();
34     int i,maxx=0,maxy=0,x,y,tx,ty;ll X=0;
35     n=read();
36     for(i=1;i<=n;i++){
37         xx[i]=read();yy[i]=read();
38         dp[N-xx[i]][N-yy[i]]+=1;
39         maxx=max(maxx,xx[i]);maxy=max(maxy,yy[i]);
40     }
41     qx[0]=N-maxx,qy[0]=N-maxy;vis[N-maxx][N-maxy]=1;
42     while(head!=tail){
43         x=qx[head];y=qy[head];head=(head+1)%maxq;
44 //        cout<<"dp "<<x<<ends<<y<<ends<<dp[x][y]<<endl;;
45         for(i=1;i<=2;i++){
46             tx=x+dx[i];ty=y+dy[i];
47             if(tx>N+maxx||ty>N+maxy) continue;
48             dp[tx][ty]=(dp[tx][ty]+dp[x][y])%MOD;
49 //            cout<<"    to "<<tx<<ends<<ty<<ends<<dp[tx][ty]<<endl;
50             if(!vis[tx][ty]){
51                 vis[tx][ty]=1;
52                 qx[tail]=tx;qy[tail]=ty;tail=(tail+1)%maxq;
53             }
54         }
55     }
56     for(i=1;i<=n;i++){
57         X=X+dp[N+xx[i]][N+yy[i]];X%=MOD;
58         X=X-((f[xx[i]*2+yy[i]*2]*finv[xx[i]*2])%MOD*finv[yy[i]*2])%MOD+MOD;
59         X%=MOD;
60     }
61     printf("%lld\n",(X*inv[2])%MOD);
62 }

 

posted @ 2018-02-22 15:50  dedicatus545  阅读(330)  评论(0编辑  收藏  举报