1. 程式人生 > >「CodePlus 2018 3 月賽」博弈論與概率統計

「CodePlus 2018 3 月賽」博弈論與概率統計

題面
自遺其咎。。。。。。
廣義卡特蘭數。
容易想到按0分時繼續扣分的次數分類,
若有i次,我們來考慮恰好有i次的方案數。
然後參考這位大佬的部落格
就可以發現這個東西是廣義卡特蘭數啊????
我怎麼不去

n > m n>m 時很好想。
n

< m n<m 時,注意對稱點和終點在對稱軸同側的話是不能用廣義卡特蘭數的。

然後一波強勢化簡就可以利用組合數的楊輝三角性質莫隊了。
A C  

C o d e AC \ Code :

#include<bits/stdc++.h>
#define maxn 500005
#define S 500
#define mod 1000000007
using namespace std;

int l[maxn],r[maxn]
,ans[maxn],fac[maxn]={1,1},invf[maxn]={1,1},inv[maxn]={1,1},Div[maxn],lb[maxn],c[maxn]; inline int C(int a,int b){ return 1ll * fac[a] * invf[b] % mod * invf[a-b] % mod; } inline bool cmp(const int &u,const int &v){ return lb[u]==lb[v]?r[u]<r[v]:lb[u]<lb[v]; } int Pow(int base,int k) { int ret=1; for(;k;k>>=1,base=1ll*base*base%mod) if(k&1) ret=1ll*ret*base%mod; return ret;} int main() { int T,p; for(int i=2;i<maxn;i++) fac[i] = 1ll * fac[i-1] * i % mod, inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod, invf[i] = 1ll * invf[i-1] * inv[i] % mod; scanf("%d%d",&T,&p); for(int i=1;i<=T;i++) { int n,m; scanf("%d%d",&n,&m); if(n < m) l[i] = n - 1, r[i] = m + n; else l[i] = m - 1 , r[i] = m + n , ans[i] = 1ll * (n - m) * C(n+m,n) % mod; Div[i] = C(n+m,n); c[i] = i,lb[i] = l[i] / S; } sort(c+1,c+1+T,cmp); int sum = 1 , L=0,R=0; for(int i=1;i<=T;i++) { for(;R<r[c[i]];R++) sum = (2ll * sum - C(R,L)) % mod; for(;R>r[c[i]];) R--,sum = 1ll * (sum+C(R,L)) * ((mod+1) / 2) % mod; for(;L<l[c[i]];) L++ , sum = (sum + C(R,L)) % mod; for(;L>l[c[i]];) sum = (sum-C(R,L)) % mod , L--; ans[c[i]] =(ans[c[i]] + sum) % mod; } for(int i=1;i<=T;i++) printf("%lld\n",(1ll*ans[i]*Pow(Div[i],mod-2)%mod+mod)%mod); }