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

SumOverPermutations


题意:

有个奇葩,组合数学很渣,老师问他:无限个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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值