2019牛客暑期多校训练营(第一场)E.ABBA
作者:互联网
考虑题目的约束条件
对于任何合法情况的前缀应满足
- A<=n+B
- B<=A+m
解释
- 贪心,A 肯定是先用 AB 的 A,再用 BA 的 A;B 同理
- 更本质的性质是对于任何前缀,当前A的最大值只能是选完所有的A,然后B全部来自BA(这样才能有更多的A可以选择),B同理
转化问题,变成从(0,0)到(n+m,n+m)的网格问题,再减去不合法的情况
设x坐标表示A的值,y坐标表示B的值
则约束条件转化为
- x<=y+n
- y<=x+m
即不能穿过两条直线,如图所示
阴影部分为合法区域
关于不合法的计算,就是平移,对称的技巧运用
例如下面的直线y=x−n,平移1,得到y=x−n−1(平移是因为要穿过直线,在直线上也是合法情况),对称点为(n+1,−(n+1)),这样(0,0)到(2∗(n+m),n+m)穿过y=x−n的情况就变成 (n+1,−(n+1))到(2∗(n+m),n+m)的情况
结果为
C(2∗(n+m),n+m)−C(2∗(n+m),m−1)−C(2∗(n+m),n−1)
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 4e3+100;
int n,m;
ll fac[maxn],invf[maxn];
ll C(ll n, ll m) { // n >= m >= 0
return n < m || m < 0 ? 0 : fac[n] * invf[m] % mod * invf[n - m] % mod;
}
void init()
{
fac[0]=invf[0]=1;
rep(i,1,4001) fac[i]=fac[i-1]*i%mod,invf[i]=powmod(fac[i],mod-2);
}
int main(int argc, char const *argv[])
{
// ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
init();
while(scanf("%d%d",&n,&m)!=EOF)
{
ll ans = 0;
ans = C(2*(n+m),n+m);
ans -= C(2*(n+m),n-1);
ans -= C(2*(n+m),m-1);
ans = (ans%mod+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
标签:ABBA,int,ll,多校,牛客,lt,ans,define,mod 来源: https://blog.csdn.net/qq_39239844/article/details/96475068