【牛客网分糖果】容斥计数DP(还是个坑)

太弱了,题解都看不懂orz orz orz orz 链接:https://www.nowcoder.com/acm/contest/173/B 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld

题目描述

N 个小朋友围成一圈,你有无穷个糖果,想把其中一些分给他们。 从某个小朋友开始,我们顺时针给他们标号为 1 ~ N。第 i 个小朋友可以得到至多 a[i],至少 1 个糖果。 问,有多少种分配方案使得每一对相邻的小朋友拿到的糖果数不同。答案对 10^9 + 7 取模。

输入描述:

第一行一个整数 N。
接下来一行 N 个整数,第 i 个数表示 a[i]。

输出描述:

一行一个整数,表示答案。
示例1

输入

复制
3
3 3 3

输出

复制
6

说明

题目限制相当于任意两人分到的糖果数不同,由乘法原理知答案为 3 * 2 * 1 = 6
示例2

输入

复制
4
4 4 4 4

输出

复制
84

备注:

对全部的测试数据,n <= 10^6, a_i <= 10^9

* 10 分的数据,n <= 4
* 10 分的数据,n <= 100, a_i <= 20
* 20 分的数据,n <= 100, a_i <= 100
* 10 分的数据,n <= 10^5, a_i 全部相等
* 30 分的数据,n <= 10^5, a_i 为随机生成
* 20 分的数据,n <= 10^6.
对于一条链,dp[i]表示从1到i的方案数,转移应该是dp[i] = dp[i-1]*a[i] 但这样就有可能算到相邻的方案数应该减去dp[i-2]*min(a[i],a[i-1])但这样又可能减多,去掉了i,i-1,i-2项都相同的情况。那么就有一个容斥方程f[i] = sigma(f[j]*(-1)^(i-j-1))(j<i),初始f[0]=1。 现在考虑对于一个环来说,最终答案应该为f[n]再减去n和1相同的情况。为保证n和1一定能取到相同的情况,并且避免分类讨论,我们把这个环绕个圈,使得a[1]为最小的那一个。那么我们如果依然按照之前的方式f[n]=sigma(f[j]*(-1)^(i-j-1))(j<i)的方程来推导,最后ans取f[n]的话,就显然会出现f[n]与f[1]取重的情况。由于取重的情况下,a[n]==a[1],此时a[n]与a[1]一一对应,那么对于1和n取重的方案应该恰好为f[n-1]种。然后就不会了orz orz orz 未完待续  
posted @ 2018-09-21 23:36  Newuser233  阅读(12)  评论(0)    收藏  举报