犬犬制作礼物

犬犬制作礼物_第1张图片

可以发现状态是三个三个的转移的

问题变为三种颜色固定数量,求相邻颜色不同的组合方案数

枚举开头的颜色A,另外两个颜色BC可以插在中间

有奇数和偶数的两种情况B,C,或者BC

然后讨论一下统计方案就行了

#include
using namespace std;
int t,m,r,g,b,ans;
const int mod=1e9+7;
int fac[2000005],inv[2000005],two[2000005];
int moc(int x)
{
	if(x>=mod) return x-mod;
	return x;
}
long long fast(int x,int y)
{
    int ans=1;
    while(y)
    {
        if(y&1) ans=1ll*ans*x%mod;
        x=1ll*x*x%mod;
        y>>=1;
    }
    return ans;
}
int cc(int n,int k)
{
    return 1ll*fac[n]*inv[k]%mod*inv[n-k]%mod;
}
int work(int n,int a,int b,int c)
{
    if(a<=0) return 0;
    int ans=0;
    for(int g=a-1;g<=a;g++)
    {
        if(g<=0) continue;
        for(int e=0;e<=g;e++)
        {
            if((g-e+b-c)&1) continue;
            int ob=(g-e+b-c)/2;
            int oc=g-e-ob;
            if(ob<0||oc<0) continue;
            if(n-a-g-e<0) continue;
            if((n-a-g-e)&1) continue;
            int r=(n-a-g-e)/2;
            ans=moc(ans+1ll*cc(g+r-1,g-1)*cc(g-e,ob)%mod*cc(g,e)%mod*two[e]%mod);
        }
    }
    return ans;
}

int solve(int m, int r, int g, int b)
{
    fac[0]=1;
    for(int i=1;i<=2000000;i++) fac[i]=1ll*fac[i-1]*i%mod;
    inv[2000000]=fast(fac[2000000],mod-2);
    for(int i=1999999;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    two[0]=1;
    for(int i=1;i<=2000000;i++) two[i]=moc(two[i-1]<<1);
    r=m-r,g=m-g,b=m-b;
    int ans=0;
    ans=(ans+2ll*work(m,r,g,b))%mod;
    ans=(ans+2ll*work(m,g,r,b))%mod;
    ans=(ans+2ll*work(m,b,g,r))%mod;
    return ans;
}
int main()
{
    scanf("%d%d%d%d",&m,&r,&g,&b);
    ans=solve(m,r,g,b);
    printf("%d\n",ans);
    return 0;
}

 

你可能感兴趣的:(思路题,构造)