版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82778499
传送门
简单组合数学想优化想了半天啊233。
我们只需考虑翻开n张A,b张B,c张C且最后一张为A的选法数。
显然还剩下
张牌没有选。
这样的话无论前
张牌怎么选,方案数会乘上一个
。
继续讨论。
我们应该从前
中选出
个A(因为最后一个一定是A)。
剩下的要么是B要么是C。
我们不妨令b+c=i。
那么有:
然后发现前面的一坨都不能优化。
只能在最后一部分做文章。
所以如何优化?
发现我们从i变到i+1的过程相当于杨辉三角向下移动一行的情况。
因此讨论一下边界分情况转移就行了。
代码:
#include<bits/stdc++.h>
#define N 300005
#define mod 1000000007
#define ll long long
using namespace std;
ll up,n,m,k;
ll ans=0,fac[N*3],ifac[N*3],mul[N*3];
inline ll calc(int a,int b){return fac[a]*ifac[b]%mod*ifac[a-b]%mod;}
inline ll ksm(ll x,int p){
ll ret=1;
while(p){
if(p&1)ret=ret*x%mod;
x=x*x%mod,p>>=1;
}
return ret;
}
int main(){
cin>>n>>m>>k,up=n+m+k,fac[0]=mul[0]=ifac[1]=ifac[0]=1;
for(ll i=2;i<=up;++i)ifac[i]=(mod-mod/i)*ifac[mod%i]%mod;
for(ll i=1;i<=up;++i)mul[i]=mul[i-1]*3%mod,(ifac[i]*=ifac[i-1])%=mod,fac[i]=fac[i-1]*i%mod;
if(m<k)m^=k,k^=m,m^=k;
for(ll i=0,j=1;i<=m+k;++i){
(ans+=calc(n-1+i,n-1)*mul[m+k-i]%mod*j%mod)%=mod;
if(i<k)(j<<=1)%=mod;
else if(i>=m)(j+=j-calc(i,k)-calc(i,i-m))%=mod;
else (j+=j-calc(i,k))%=mod;
}
cout<<(ans+mod)%mod;
return 0;
}