「CodePlus 2018 3 月賽」博弈論與概率統計
阿新 • • 發佈:2019-01-13
題面
自遺其咎。。。。。。
廣義卡特蘭數。
容易想到按0分時繼續扣分的次數分類,
若有i次,我們來考慮恰好有i次的方案數。
然後參考這位大佬的部落格
就可以發現這個東西是廣義卡特蘭數啊????
我怎麼不去
時很好想。
時,注意對稱點和終點在對稱軸同側的話是不能用廣義卡特蘭數的。
然後一波強勢化簡就可以利用組合數的楊輝三角性質莫隊了。
:
#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);
}