【NOIP2013模拟】粉刷匠 题解&代码
2016-05-30 20:22
211 查看
原题
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
33
1 2 3
5
2 2 2 2 2
10
1 1 2 2 3 3 4 4 5 5
Sample Output
1039480
85937576
Data Constraint
30% N≤10,T≤550% N≤15,T≤5
80% K≤15,Ci≤5,T≤500
100% K≤15,Ci≤6,T≤2000
题解
每一步处理一种颜色。设 F[i][j] 表示涂到第i种颜色,有j对相邻的柱子颜色相同。
记涂到第i种颜色之后一共有 S 块。
对于 i+1 这种颜色,能粉刷 A 次。
设把这种颜色分成 k 块,插进序列里面。
插进的位置中,有 l 个位置刚好插进在j对颜色相同的柱子中间( l≤j 且 l≤k )。
新状态的 j:原有的 j,新增的 A−k,减少的 l。
状态转移:
把颜色分成 k 块的方案数:C(A−1,k−1)
把块插进 l 个位置的方案数:C(j,l)
剩余块的处理方式:C(S+1−j,k−l)
转移方程如下:
F[i+1][j+A−k−l]+=F[i][j]∗C(j,l)∗C(A−1,k−1)∗C(S+1−j,k−l)
时间复杂度O(K∗N∗C∗C∗T)。(理论复杂度与上一解法一致)
优化
我们看到 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 ,c ; 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 [0]); } return 0; }
相关文章推荐
- HashMap源代码
- Easy-题目34:119. Pascal's Triangle II
- python之路
- Java 并发工具包 java.util.concurrent 用户指南
- Storm 编程入门
- 获取客户端的代码
- 在C++中使用Protocol Buffer
- Atom 检测php错误扩展linter-php
- Python之numpy教程(四):数据处理、绘图、数据统计分析
- C语言课设-1
- 69道Spring面试题和答案
- C++独孤九剑第一式——拨云见日(对象内存模型)
- Java跨域设置
- 基因数据处理42之mango问题_seqdict.avro不存在解决
- Intent中的四个重要属性——Action、Data、Category、Extras
- 宏、函数、宏函数,内联函数的区别
- go 初使用
- 331. Verify Preorder Serialization of a Binary Tree
- python+webpy, to deploy the Nao Controller Server
- excel中用当天日期命名工作表名vba