码迷,mamicode.com
首页 > 其他好文 > 详细

TC Srm 597 Div 1 T3

时间:2015-06-18 08:14:38      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:

题意:

给出M,R,G,B,2M=R+B+G,M代表一个2*M区域的列数,RGB分别代码红绿蓝格子的个数,要求:每个2*2格子中,三种颜色每种至少有一个格子,且相邻格子颜色不同,问有多少种排列方式

首先我们发现可以把一列两格的放置方案分为两组,{RB,BG,GR},{BR,GB,RG}

一个合法方案必定只由其中的一组组成,因此我们可以计算一组的方案,然后将其×2即可

那么我们假设RB有x个,BG有y个,GR有z个,那么ans等价于:求使得BR,RG,GB分别不能与自己相邻的放置方案数。

 

我们假设x>y>z,首先我们要用 y,z去填补x之间的空缺,

如果y+z<x-1,则无法填补,返回0

否则,我们有4种方案,填中间x-1个,左边x个,右边x个,全部x+1个,我们对于x-1~x+1分别计算即可

 

那么现在有nx(nx=x+1/x/x-1)个空,我们要用y,z去填,

1.首先我们假设用y填y1个空,方案为C(nx,y-1),用z填z1=x-y1个空

2.设多出的y2=y-y1,把y2塞进去的方案等价于把所有的y分成 y1份的方案数,为C(y-1,y1-1)

对于每个多塞的y,我们要塞一个z来防止y相邻,那么塞完y后我们剩的z为z2=z-z1-y2,再将这些z分别插个y1个序列的两端,方案为C(2*y1,z2)

至此,分配结束

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;
typedef long long ll;

int N=1000000;
int mo=1000000007;
int jc[1000011],fc[1000011];
int ans,tmp,ts,x,y,z,xl,yl,req,zl,dt,tj,M,R,G,B,j,i;

int mi(int x,int z)
{
    int l;
    l=1;
    while(z){
        if(z%2==1)l=(ll)l*x%mo;
        x=(ll)x*x%mo;
        z/=2;
    }
    return l;
}

int C(int n,int m)
{
    return (ll)jc[n]*fc[m]%mo*fc[n-m]%mo;
}

int main()
{
    jc[0]=1;
    for(i=1;i<=N;i++)jc[i]=(ll)jc[i-1]*i%mo;
    fc[N]=mi(jc[N],mo-2);
    for(i=N-1;i>=0;i--)fc[i]=(ll)fc[i+1]*(i+1)%mo;
    scanf("%d",&dt);
    for(tj=1;tj<=dt;tj++){
        scanf("%d%d%d%d",&M,&R,&G,&B);
        x=M-B;y=M-R;z=M-G;
        if(x<0||y<0||z<0){
            printf("0\n");
            continue;
        }
        ans=0;
        if(y>x)swap(x,y);
        if(z>x)swap(x,z);
        if(z>y)swap(y,z);
        if(y+z<x-1){
            printf("0\n");
            continue;
        }
        for(xl=x-1;xl<=x+1;xl++){
            if(y+z<xl)continue;
            tmp=0;
            for(j=1;j<=y;j++){
                req=xl-j;
                if(req>z)continue;
                yl=y-j;
                if(req+yl>z)continue;
                ts=C(xl,j);
                ts=(ll)ts*C(y-1,j-1)%mo;
                zl=z-req-yl;
                if(zl>2*j)continue;
                ts=(ll)ts*C(2*j,zl)%mo;
                tmp=(tmp+ts)%mo;
            }
            if(xl==x)tmp=tmp*2%mo;
            ans=(ans+tmp)%mo;
        }
        ans=(ans*2)%mo;
        printf("%d\n",ans);
    }
}

 

TC Srm 597 Div 1 T3

标签:

原文地址:http://www.cnblogs.com/applejxt/p/4584852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!