【NOIP2013模拟】粉刷匠 题解&代码

原创 2016年05月30日 20:22:14

原题

Description

赫克托是一个魁梧的粉刷匠,而且非常喜欢思考= =

现在,神庙里有N根排列成一直线的石柱,从1到N标号,长老要求用油漆将这些石柱重新粉刷一遍。赫克托有K桶颜色各不相同的油漆,第i桶油漆恰好可以粉刷Ci根石柱,并且,C1+C2+C3…CK=N(即粉刷N根石柱正好用完所有的油漆)。长老为了刁难赫克托,要求相邻的石柱颜色不能相同。

喜欢思考的赫克托不仅没有立刻开始粉刷,反而开始琢磨一些奇怪的问题,比如,一共有多少种粉刷的方案?

为了让赫克托尽快开始粉刷,请你尽快告诉他答案。

Input

第一行一个正整数T,表示测试数据组数

对于每一组测试数据数据:

第1行:一个正整数K

第2行:K个正整数,表示第i桶油漆可以粉刷的石柱个数,Ci。

Output

对于每组输入数据,输出一行一个整数,表示粉刷的方案数mod 1000000007。

Sample Input

3

3

1 2 3

5

2 2 2 2 2

10

1 1 2 2 3 3 4 4 5 5

Sample Output

10

39480

85937576

Data Constraint

30% N10,T5

50% N15,T5

80% K15,Ci5,T500

100% K15,Ci6,T2000

题解

  • 每一步处理一种颜色。

  • F[i][j] 表示涂到第i种颜色,有j对相邻的柱子颜色相同。

  • 记涂到第i种颜色之后一共有 S 块。

  • 对于 i+1 这种颜色,能粉刷 A 次。

  • 设把这种颜色分成 k 块,插进序列里面。

  • 插进的位置中,有 l 个位置刚好插进在j对颜色相同的柱子中间( lj 且 lk )。

  • 新状态的 j:原有的 j,新增的 Ak,减少的 l

  • 状态转移:

    1. 把颜色分成 k 块的方案数:C(A1,k1)

    2. 把块插进 l 个位置的方案数:C(j,l)

    3. 剩余块的处理方式:C(S+1j,kl)

  • 转移方程如下:

  • F[i+1][j+Akl]+=F[i][j]C(j,l)C(A1,k1)C(S+1j,kl)

  • 时间复杂度O(KNCCT)。(理论复杂度与上一解法一致)

优化

  • 我们看到 T=2000 这一条件极不和谐。

  • 庆幸的是,将每个询问内的数字打乱顺序不影响答案。

  • 我们可以将每个询问内部进行排序,再按字典序排序之后再处理,顺序处理。

  • 处理询问 i+1 时,保留处理i时的f值。

  • 若询问i与 i+1 的询问前x个数都相等,则对于x之前的f值都是相等的。

  • 由于按字典序排序了,顺序处理会减少大多数的处理。

Code

#include<cstdio>
#include<cstring>
using namespace std;
const int mo=1e9+7,N=91;
long long f[N][N],c[N][N];
inline int read()
{
    int data=0; char ch=0;
    while(ch<'0' || ch>'9') ch=getchar();
    while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
    return data;
}
int main()
{
    c[0][0]=1;
    for(int i=1;i<N;i++)
    {
        c[i][i]=c[i][0]=1;
        for(int j=1;j<i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
    }
    int T=read();
    while(T--)
    {
        int n=read(),m=0;
        memset(f,0,sizeof(f));
        f[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            int x=read();
            for(int j=0;j<=m;j++)
                if(f[i-1][j])
                    for(int k=1;k<=x;k++)
                    {
                        int y=(x<j)?x:j;
                        for(int l=0;l<=y;l++)
                            f[i][j-l+x-k]=(f[i][j-l+x-k]+f[i-1][j]*c[x-1][k-1]*c[j][l]%mo*c[m-j+1][k-l])%mo;
                    }
            m+=x;
        }
        printf("%lld\n",f[n][0]);
    }
    return 0;
}
版权声明:本文是蒟蒻写出来的,神犇转载也要说一声哦!

相关文章推荐

【NOIP2013模拟】粉刷匠

Description给出n个球,其中有C1个球是颜色1的,有C2个球是颜色2的,有C3个球是颜色3的…… 有Ck个球是颜色k的。求相邻两个球颜色不同的排列方案。 k...

【NOIP2013模拟】Vani和Cl2捉迷藏 题解&代码

原题Descriptionvani和cl2在一片树林里捉迷藏……这片树林里有N座房子,M条有向道路,组成了一张有向无环图。树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。如果从房子A...

【NOIP2013模拟】Freda的传呼机 题解+代码

这题又有点像码农题!!Description为了 随时 与 rainbow快速交流, Freda制造了 两部传呼机 。Freda和 rainbow所在的地方有N座房屋、M条双向 光缆 。每条光缆连接两...

【NOIP2013模拟联考2】三角阵(tri) 题解

原题Description把3个相同的小三角形按如下方式连接起来就形成了一个一级三角阵。我们把位于顶端的小三角形标记为T,位于左端的小三角形标记为L,位于右端的小三角形标记为R。把3个一级三角阵按同样...

【NOIP2013模拟联考5】军训(training) 题解

原题DescriptionHYSBZ 开学了!今年HYSBZ 有n 个男生来上学,学号为1…n,每个学生都必须参加军训。在这种比较堕落的学校里,每个男生都会有Gi 个女朋友,而且每个人都会有一个欠扁值...

NOIP2013提高组 华容道 题解+代码

华容道……Description小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。小...

NOIP 2013 提高组题解 【附AC代码】

NOIP2013 提高组题解

【NOIP2016A组模拟7.13】亚瑟王之宫 题解+代码

DescriptionInputoutput答案Sample Input4 4 4 1 1 4 1 1 4 4 4Sample Output4Data ConstraintR,C

noip2013详细题解

  • 2014年07月07日 12:33
  • 289KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【NOIP2013模拟】粉刷匠 题解&代码
举报原因:
原因补充:

(最多只允许输入30个字)