N排列盒子涂色方法总和 DP SRM 666 div1 medium SumOverPermutations

来源:互联网 发布:知乎页面改版 编辑:程序博客网 时间:2024/06/05 05:05

SumOverPermutations

http://community.topcoder.com/stat?c=problem_statement&pm=13764&rd=16515

题解摘自http://www.cnblogs.com/HarryGuo2012/p/4777063.html

题意:

有个奇葩,组合数学很渣,老师问他:无限个n种颜色的球放在n个有顺序的盒子中,每个盒子放一个,相邻盒子的球的颜色不同,有多少种方法。这个奇葩给了个奇葩的解答,他说这和放的顺序有关,比如有三个盒子,三种颜色的球,若放的顺序是 1 2 3,那么答案就是3×2×2,若放的顺序是 1 3 2,那么答案就是3×3×1。更一般的,他认为,若一个位置的左侧和右侧都被放了,那么现在有(n-2)种可能性,若只有一侧被放了,那么有(n-1)种可能性,若两侧都没放,那么有n种可能性。我们知道这是明显错误的,但是,题目就是问你,给你个n,这n!种放的顺序按照这个奇葩的算法得到的答案是多少。

题解:

dp[i]  表示n种颜色放在i个盒子中,答案是多少。那么转移就只有两种情况:

一种是将第i个球放在边界上,这种的转移是dp[i]=2dp[i1](n1),第一项的2表示左右两个边界,第二项dp[i1]表示i1时的情况,第三项n1表示由于第i个球在边界,所以只乘n1

另外一种是将第i个球放在中间某个位置,假设其左侧有j个球,那么转移必然是

dp[i]=j=1i2Cji1dp[j]dp[ij1](n2)

所以总的转移是

dp[i]=(j=1i2Cji1dp[j]dp[ij1](n2))+2dp[i1](n1)

答案显然是dp[n]


long long dp[MAX_N];long long mod=1000000007;long long C[MAX_N][MAX_N];class SumOverPermutations{        public:        int findSum(int n)        {            C[0][0]=1;            for(int i=1;i<=n;i++)                for(int j=0;j<=i;j++)                    C[i][j]=(j==0?1:C[i-1][j-1]+C[i-1][j])%mod;            dp[1]=n%mod;            dp[2]=n%mod*(n-1)%mod*2%mod;            for(int i=3;i<=n;i++){                dp[i]=2%mod*(n-1)%mod*dp[i-1]%mod;                for(int j=1;j<=i-2;j++)                    dp[i]=(dp[i]+C[i-1][j]%mod*dp[j]%mod*dp[i-j-1]%mod*(n-2)%mod)%mod;            }            return dp[n]%mod;        }};

0 0
原创粉丝点击