题面
自遗其咎。。。。。。
广义卡特兰数。
容易想到按0分时继续扣分的次数分类,
若有i次,我们来考虑恰好有i次的方案数。
然后参考这位大佬的博客
就可以发现这个东西是广义卡特兰数啊????
我怎么不去
n > m n>m n>m时很好想。
n < m n<m n<m时,注意对称点和终点在对称轴同侧的话是不能用广义卡特兰数的。
然后一波强势化简就可以利用组合数的杨辉三角性质莫队了。
A C C o d e AC \ Code AC Code:
#include
#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);
}