TC Srm 597 Div 1 T3

题意:

给出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);
    }
}
时间: 2024-08-29 04:21:47

TC Srm 597 Div 1 T3的相关文章

TC Member SRM 478 DIV 1(CarrotJumping-操作观察)

Problem Statement   Rabbits often feel hungry, so when they go out to eat carrots, they jump as quickly as possible. Initially, rabbit Hanako stands at position init. From position x, she can jump to either position 4*x+3 or 8*x+7 in a single jump. S

[TC SRM 697 div1 lev1] DivisibleSetDiv1

Tutorial:https://apps.topcoder.com/wiki/display/tc/SRM+697#DivisibleSetDiv1 Note:证明过程值得一看. 主要内容:寻找[x1,x2,...,xn]使得满足bi * xi >= S - xi,其中S = x1 + x2 + ... + xn.

TopCoder SRM 634 Div.2[ABC]

TopCoder SRM 634 Div.2[ABC] ACM 题目地址: TopCoder SRM 634 赛后做的,感觉现场肯定做不出来Orz,简直不能多说. Level One-MountainRanges[水题] 题意: 问序列中有几个完全大于旁边的峰. 分析: 傻逼题,不多说. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: one.cpp * Create Date: 2014-09-26 21:01:23 * Desc

[topcoder]SRM 633 DIV 2

第一题,http://community.topcoder.com/stat?c=problem_statement&pm=13462&rd=16076 模拟就可以了. #include <vector> #include <algorithm> using namespace std; class Target { public: vector <string> draw(int n) { vector<string> result(n,

[topcoder]SRM 646 DIV 2

第一题:K等于1或者2,非常简单.略.K更多的情况,http://www.cnblogs.com/lautsie/p/4242975.html,值得思考. 第二题:http://www.cnblogs.com/lautsie/p/4245242.html BFS和DFS都可以,注意的是,写的时候,可以往que里几个东西一起扔,就不用建立对象了.也可以直接用二维矩阵记录blocked和visited. 剪枝什么的,最基本的是发现其实在步数限制的情况下,棋盘就是有界的了. 第三题:http://ap

TopCoder SRM 628 DIV 2

250-point problem Problem Statement    Janusz is learning how to play chess. He is using the standard chessboard with 8 rows and 8 columns. Both the rows and the columns are numbered 0 through 7. Thus, we can describe each cell using its two coordina

竞赛图的得分序列 (SRM 717 div 1 250)

SRM 717 DIV 1 中 出了这样一道题: 竞赛图就是把一个无向完全图的边定向后得到的有向图,得分序列就是每个点的出度构成的序列. 给出一个合法的竞赛图出度序列, 要求构造出原图(原题是求(u, v)有路径的点对数,似乎有不需要构造出原图的方法). 当时我的做法是 直接构造一个网络,跑最大流. 比赛后总觉得这个题有什么神奇的性质,于是搜了一下相关资料: 有一篇关于得分序列的论文:http://www.sciencedirect.com/science/article/pii/0095895

TC srm 673 300 div1

TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能够组成一个骑兵,这个骑兵的战斗力等于马的战斗力乘以人的战斗力,问你有多少种组合方式满足其他骑兵的战斗力都不超过第0号骑兵. Input Output Sample Input Sample Output HINT 题意 题解: 大概就暴力枚举哪匹马和第0号人匹配,后面的骑兵我们按照战斗力从大到小排序之后,

TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization &amp; Codeforces 839 E

传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相加,含有n个不同变量的式子的最大值. 另外限制了每一个变量的最大最小值R[i]和L[i]和所有变量之和的最大值Max. n<=13 题外话: 刚开始做这道题的时候,感觉意外眼熟? codeforces 839 E(此题的退化版):http://codeforces.com/contest/839/pro