小米网络赛 热身赛 A题 ABBA
Pro:
https://ac.nowcoder.com/acm/contest/8409/A
计算满足可以划分为\(n\)对\(AB\)和\(m\)对\(BA\)的长度为\(2*(n+m)\)的AB序列个数
\(n,m<=1e6\)
Sol:
考虑怎么判断一个序列是否合法
可以从左到右依次处理
记录当前有x个A,y个B
\(x<=n\)且\(y<=m\)时显然是合法的
因为从贪心的角度想
前\(n\)个\(A\)和前\(m\)个\(B\)一定要分别用来构成\(AB\)和\(BA\)
当\(x>n\)时,则每一个a都需要用来组成\(BA\)
这时就要求每一个A都能找到一个B
写成不等式的形式就是\(x-n<=y\)
同理可得\(y-m<=x\)
简单处理这两个人不等式后可得\(-n<=y-x<=m\)
这个问题就转为了带有两条直线限制的NE Latice Path问题
可以DP,也可以直接算
直接算的话就是这个题:https://www.luogu.com.cn/problem/P3266
直接上板子就可以了
板子链接:https://www.cnblogs.com/Creed-qwq/p/10292933.html
#include<bits/stdc++.h>
#define N 11000000
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
const int h=3,ki=149,mo=1e9+7;
int mod(int x){return (x%mo+mo)%mo;}
int inc(int x,int k){x+=k;return x<mo?x:x-mo;}
int dec(int x,int k){x-=k;return x>=0?x:x+mo;}
int ksm(int x,int k)
{
int ans=1;
while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}
return ans;
}
int inv(int x){return ksm(mod(x),mo-2);}
int read()
{
char ch=0;int x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
return x*flag;
}
void write(int x)
{
if(!x)return (void)putchar(48);
if(x<0)putchar(45),x=-x;
int len=0,p[20];
while(x)p[++len]=x%10,x/=10;
for(int i=len;i>=1;i--)putchar(p[i]+48);
}
const db eps=1e-7,inf=1e9+7,pi=acos(-1);
db Read(){db x;scanf("%lf",&x);return x;}
void Write(db x){printf("%lf",x);}
int fac[N],vac[N];
void prepare(int n)
{
fac[0]=1;for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mo;
vac[n]=inv(fac[n]);for(int i=n;i>=1;i--)vac[i-1]=1ll*vac[i]*i%mo;
}
int C(int n,int m){return n>=m?1ll*fac[n]*vac[m]%mo*vac[n-m]%mo:0;}
void fold(int &x,int &y,int k){swap(x,y);x-=k;y+=k;}
int solve(int n,int m){return (n>=0&&m>=0)?C(n+m,n):0;}
int work(int n,int m,int l,int r)
{
l--;r++;
int x,y,ans=solve(n,m);
x=n;y=m;
while(true)
{
fold(x,y,l);if(x<0||y<0)break;ans=dec(ans,solve(x,y));
fold(x,y,r);if(x<0||y<0)break;ans=inc(ans,solve(x,y));
}
x=n;y=m;
while(true)
{
fold(x,y,r);if(x<0||y<0)break;ans=dec(ans,solve(x,y));
fold(x,y,l);if(x<0||y<0)break;ans=inc(ans,solve(x,y));
}
return ans;
}
int main()
{
prepare(1e7);
int n,m;
while(~scanf("%d%d",&n,&m))write(work(n+m,n+m,-n,+m)),putchar('\n');
return 0;
}