拯救者 Y9000P v.s. R9000P:10 款遊戲 11 代酷睿平均領先 5%
阿新 • • 發佈:2021-06-22
題面傳送門
代數推導天地滅,組合意義保平安。
首先我們發現如果我們預處理組合數然後暴力計算是\(O(n^2)\)的很難優化。
我們考慮換一個思路。
我們知道\(C^{a_i+b_i}_{a_i}\)是從\((0,0)\)走到\((a_i,b_i)\)的方案數。
那麼原題目要求的就是\((-A_i,-B_i)\)走到\((A_j,B_j)\)的方案數。
這個東西很好算,我們設\(dp_{i,j}\)為點\((i,j)\)走到任意一個第三象限點的方案數,那麼就可以遞推計算。
注意減掉\(i=j\)再去重。時間複雜度\(O(Maxa\times Maxb+n)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define re register #define ll long long #define db double #define N 2000 #define M 200000 #define mod 1000000007 #define eps (1e-7) #define U unsigned int #define IT set<ques>::iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) using namespace std; int n,m,x[M+5],y[M+5],Maxx,Maxy;ll ans,G[N+5<<1][N+5<<1],frc[N+5<<2],inv[N+5<<2]; I ll mpow(ll x,int y=mod-2){ll ans=1;while(y) (y&1)&&(ans=ans*x%mod),x=x*x%mod,y>>=1;return ans;} int main(){ freopen("1.in","r",stdin); re int i,j;scanf("%d",&n);for(i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]),Maxx=max(Maxx,x[i]+1),Maxy=max(Maxy,y[i]+1); for(i=1;i<=n;i++) G[Maxx-x[i]][Maxy-y[i]]++;frc[0]=inv[0]=1;for(i=1;i<=2*(Maxx+Maxy);i++) frc[i]=frc[i-1]*i%mod,inv[i]=inv[i-1]*mpow(i)%mod; for(i=1;i<=Maxx*2;i++)for(j=1;j<=Maxy*2;j++) G[i][j]=(G[i][j]+G[i-1][j]+G[i][j-1])%mod;for(i=1;i<=n;i++) ans+=G[x[i]+Maxx][y[i]+Maxy]-frc[(x[i]+y[i])*2]*inv[x[i]*2]%mod*inv[y[i]*2]%mod; printf("%lld\n",(ans%mod+mod)*mpow(2)%mod); }