直接上代码吧?不能这样!!
2026-02-01 18:44:14
发布于:湖南
2阅读
0回复
0点赞
我们可以构造一个类似于卡特兰数的图像,设定向上走为 A 胜利,向右走为 B 胜利,最终到达点 (n,m) 本局结束。

图中两条绿线在构造直线下到达终点 (n,m) ,为合法方案,图中红线越过了直线,为非法方案。
同理,我们推广到 A 得分为 n−m+1 时就是将直线向上平移 1,简单容斥我们可得到此时的合法方案就是通过了它平移前的直线且没有通过平移后的直线所构成的合法方案。
我们可以通过对称起点,构造所有不合法的方案(下图中粉线),针对平移后的直线合法方案就是所有方案减去非法方案,即:

通过错位相减,我们可以将原式化为:

然后自己看吧!!
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,mod=1e9+7;
int T,p,x[N],y[N],ans[N],len,fin[N],l,ifin[N],res=2;
int get(int x) {return x/len;} struct node {int x,k,id;} q[N];
inline int ksm(int a,int b) {int res=1; while(b) {if(b&1) res=(res*a)%mod; a=(a*a)%mod; b>>=1;} return res;}
bool cmp(node a,node b) {if(get(a.x) == get(b.x)) return a.k < b.k; return a.x < b.x;}
inline int C(int n,int k) {if(n < k) return 0; return ((fin[n]*ifin[n-k])%mod*ifin[k])%mod;}
signed main()
{
scanf("%lld%lld",&T,&p);
for(int i=1;i<=T;i++)
{
scanf("%lld%lld",&x[i],&y[i]);
q[i].x=x[i]+y[i]; q[i].id=i; l=max(l,q[i].x); q[i].k=min(x[i],y[i])-1;
}
len=max(1LL,(int)sqrt(l)); sort(q+1,q+T+1,cmp);
fin[0]=1; for(int i=1;i<=l;i++) fin[i]=fin[i-1]*i%mod;
ifin[l]=ksm(fin[l],mod-2); for(int i=l;i>=1;i--) ifin[i-1]=ifin[i]*i%mod;
for(int i=1;i<=T;i++) if(x[i]>=y[i]) ans[i]=(x[i]-y[i])*C(x[i]+y[i],x[i])%mod;
int n=1,k=1,i2=ksm(2,mod-2);
for(int i=1;i<=T;i++)
{
int n1=q[i].x,k1=q[i].k;
while(n > n1) res=(res+C(n-1,k))*i2%mod,n--;
while(n < n1) res=(res*2-C(n,k)+mod)%mod,n++;
while(k > k1) res=(res-C(n,k)+mod)%mod,k--;
while(k < k1) res=(res+C(n,k+1))%mod,k++;
ans[q[i].id]=(ans[q[i].id]+res)%mod;
}
for(int i=1;i<=T;i++) printf("%lld\n",(ans[i]*ksm(C(x[i]+y[i],x[i]),mod-2)%mod)%mod);
return 0;
}
这里空空如也







有帮助,赞一个