题面
link
\(n\) 个人排成一个环,第i个人有\(a_i\)个球,每个人可以拿出x个(\(x\in[0,a_i]\))给后面一个人,这个过程只进行一次。设传完后每个人手里有\(x_i\)个球,求所有情况(值\(x_i\)所成的序列不同)下\(\prod_{i=1}^nx_i\)的总和。
题解
感觉完全没有突破口,可能只有做过类似的题目才会吧...
主要是对\(\prod_{i=1}^nx_i\)的转化:变换后从每个人的球中选一个拿出来的方案数。
转移的关键:每个人拿出来的球是本来就是自己的,还是上一个人给你的。
为了方便转移:状态的设计也很巧妙
- \(f[i][0]:\)表示第\(i\)个人从自己原本有的球中选球,考虑前\(i-1\)个人的方案数
- \(f[i][1]:\)表示第\(i\)个人的球是上一个人的,考虑前\(i\)个人的方案数
那么考虑转移,我们暴力的枚举给下一个人的球是多少:
\[f[i+1][0]=f[i][0]\sum_{j=mi}^{a[i]}(a[i]-j)+f[i][1]\sum_{j=mi}^{a[i]}1\\ f[i+1][1]=f[i][0]\sum_{j=mi}^{a[i]}j(a[i]-j)+f[i-1][1]\sum_{j=mi}^{a[i]}j \]解释:
- \(dp[i][0]\rightarrow dp[i+1][0]\),由于\(dp[i][0]\)没算第i个人的选球方案,所以要在转移时把它加上。如果第\(i\)个人给了\(j\)个球,就有\(a_i-j\)种拿球方案.
- \(dp[i][1]\rightarrow dp[i+1][0]\),这时是算上了第i个人的选球方案,而且不需要算下一个人的,所以只需算上传球的方案数。
- \(dp[i][0]\rightarrow dp[i+1][1]\),这个时候的转移需要算上第i个人和第i+1个人的选球方案,而且第i+1个人选的是第i个人的球。如果第i个人给了j个球,第i个人就剩下\(a_i-j\)个球,方案数为\(j(a_i-j)\),
- \(dp[i][1]\rightarrow dp[i+1][1]\),这个时候只需要算上第i+1个人的方案,而第i+1个人选的是第i个人的球,如果第i个人给了j个球,就有j种拿球方案
优化:
\[\sum_{j=0}^xj=\frac{x(x+1)}{2}\\ \sum_{j=0}^xj^2=\frac{x(x+1)(2x+1)}{6} \] 有人会问:为什么要mi?那是因为只有\(x_i\)所成序列不同才算入贡献,分析什么情况下才会有重复。设\(c_i\)是第\(i\)个人给后面的人的数量,发现如果\(min(c_i)\ne 0\)的时候,可以给每个\(c_i\)减一,发现其\(x\)和变换之后的\(x'\)一样。那么就需要控制\(min(c_i)= 0\)。
但你不好处理,所以通过容斥,将\(mi=0\)减去\(mi=1\)的情况就是答案。
ps:因为是个环,你还需要处理初值是\(f[1][0]\)还是\(f[1][1]\)。具体见代码:code
启发
- 积累了一个trick!\(\prod_{i=1}^nx_i\)转化:从每个人的球中选一个拿出来的方案数。
- 平方和公式!
- 后面的去重处理也可以有多种运用!