Problem Statement
(N) people called Person (1,2,…,N) are standing in a circle.
For each (1≤i≤N−1), Person (i)'s neighbor to the right is Person (i+1), and Person (N)'s neighbor to the right is Person (1).
Person (i) initially has (a_{i}) balls.
They will do the following procedure just once.
- Each person chooses some (possibly zero) of the balls they have.
- Then, each person simultaneously hands the chosen balls to the neighbor to the right.
- Now, make a sequence of length (N), where the (i)-th term is the number of balls Person (i) has at the moment.
Let (S) be the set of all sequences that can result from the procedure. For example, when (a=(1,1,1)), we have (S={(0,1,2),(0,2,1),(1,0,2),(1,1,1),(1,2,0),(2,0,1),(2,1,0)})
Compute (∑_{x∈S}∏^{N}_{i=1}x_i), modulo 998244353.
Constraints
- All values in input are integers.
- (3≤N≤10^5)
- (0≤a_i≤10^9)
Input
Input is given from Standard Input in the following format:
N
a1 a2 ⋯⋯ aN
Output
Print (∑_{x∈S}∏^{N}_{i=1}x_i), modulo 998244353.
Sample Input 1 Copy
Copy
3
1 1 1
Sample Output 1 Copy
Copy
1
- We have (S={(0,1,2),(0,2,1),(1,0,2),(1,1,1),(1,2,0),(2,0,1),(2,1,0)})
- (∑_{x∈S}∏^{N}_{i=1}x_i) is 11.
Sample Input 2 Copy
Copy
3
2 1 1
Sample Output 2 Copy
Copy
6
Sample Input 3 Copy
Copy
20
5644 493 8410 8455 7843 9140 3812 2801 3725 6361 2307 1522 1177 844 654 6489 3875 3920 7832 5768
Sample Output 3 Copy
Copy
864609205
- Be sure to compute it modulo 998244353.
题目翻译
有n个人,环形排列,每个人有(a_i)个球,每个人同一事件给下一个传递任意数量自己的球。
设(S)为不相同的最终状态的集合,求(∑_{x∈S}∏^{N}_{i=1}x_i)
题目解析
首先是,考虑什么情况下两种不同的传递方案可以得到相同的结果
显然传递序列(1,1,2,2)和(2,2,3,3)的最终状态是等价的
归纳得出:两次传递等价满足传递序列的差分序列相同,则最终状态等价
上面两个传递序列差分序列均为(-1,0,1,0)
如何除去等价的传递?如果传递序列,如果最小值大于0,那么一定存在更小的等价传递序列
故可以得出最终方案数:(prod_{i=1}^{n}{a_i+1}-prod_{i=1}^{n}{a_i})
但是原题并不是求最终方案数,但是最终方案数的计算可以启发:利用容斥原理排除等价的状态
第二个重点是答案需求的表达式,首先(∏^{N}_{i=1}x_i)可以表示为第(i)个人各自在自己最后拥有的(x_i)球中选一个的方案数
这样原题就转换为了分类讨论第(i)个人选的一个球分别是前面的人,还是自己的方案数。可以用动态规划解决
令(f[i][j](j=0/1)),当(j=0)时,(f[i][0])表示第 (i)个人从自己原本有的球中选球,前 (i−1)个人选球的方案数(不考虑自己)。当(j=1)时,(f[i][1])表示第 (i)个人从前面的球中选球,前 (i)个人选球的方案数(考虑自己的方案数)
之所以区分(j=0)和(j=1)不同来源的表达方式,是为了独立不同来源的球
同时注意:前一个人传多少给下一个人与下一个人传出多少之间没有关系。也就是说,传递都是同时发生的
这里设(S(n)=sum_{i=1}^n i=frac{n(n+1)}{2}) (g(n)=sum_{i=1}^{n}{i^2}={frac{n(n+1)(2n+1)}{6}})
(f[i][0]->f[i+1][0])因为(f[i][0])没有计算第(i)个人的方案,故(f[i+1][0]+=f[i][0]*S(a_i))
(f[i][1]->f[i+1][0])因为算上了第(i)个人方案,只需算上传球方案(f[i+1][0]+=f[i][1]*(a_i+1))
(f[i][0]->f[i+1][1])因为没有计算第(i)个人,故需要计算(i)和(i+1)的方案,假如第(i)个人剩(k)个球,第(i+1)人拿(a_i-k)个球,总方案为(sum_{k=1}^{a_i}{k*(a_i-k)}=a_i*S(a_i)-g(a_i)),有(f[i+1][1]+=f[i][0]*(a_i*S(a_i)-g(a_i)))
(f[i][1]->f[i+1][1])只要计算第(i+1)个人从第(i)个人获得球的方案,(f[i+1][1]+=f[i][1]*S(a_i))
上面的转移已经体现了区分(j=0)方案不包括(i)自己和(j=1)方案包括(i)的作用,当第(i)个人选择自己原有的球,第(i+1)人选择(i)传递的球,那么显然此时两个人的方案应该一起计算。同时(i+1)选择(i)传递的球,(i)选择(i-1)传递的球
由于转移是一个环,(i=n)需要转移到(i=1)。则需要先钦定第1个人是选自己的球还是选第 n 个人传的球(初值设为1,另一个设为0),然后转移一圈。如果初始化钦定 $f[1][0]=1,f[1][1]=0 $ ,那么最终答案就是(f[1][0]-1),反过来是一样的。
最后考虑传球最小值不为0的容斥,在调用一次DP并在模拟传球过程中限制传球数不为0。将之前DP的答案减去约束后得到的即为满足不等价条件的方案数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
int n,a[100005];
int Mod=998244353;
ll f[100005][2],inv2,inv3;
ll qpow(ll x,int k){
ll res=1;
while (k){
if (k&1) res=res*x%Mod;
x=x*x%Mod;
k>>=1;
}
return res;
}
ll dp(int init,int zero){//init表示dp[1][]的初值,zero表示是否不允许0传递
memset(f,0,sizeof(f));
f[1][0]=init;f[1][1]=init^1;
for (int i=1;i<=n;i++){
int to=i%n+1;
ll s=(a[i]-zero+Mod)%Mod;
//转移时,剩余值为a[i]不合法,因为剩余a[i]代表转移为0
ll s1=s*(s+1)%Mod*inv2%Mod;
f[to][0]=(f[to][0]+f[i][0]*s1%Mod)%Mod;
f[to][0]=(f[to][0]+f[i][1]*(s+1)%Mod)%Mod;
if (zero) s++;
//因为对于f[to][1]的转移,传递值0的情况计数为0不会计入结果
//to选的球是来自i的球,所以此处表示传递值的a[i]合法
ll s2=s*(s+1)%Mod*inv2%Mod;
ll s3=s*(s+1)%Mod*(s*2+1)%Mod*inv2%Mod*inv3%Mod;
f[to][1]=(f[to][1]+f[i][0]*(s2*s%Mod-s3+Mod)%Mod)%Mod;
f[to][1]=(f[to][1]+f[i][1]*s2%Mod)%Mod;
}
if (init) {
f[1][0]-=1;
return (f[1][0]+Mod)%Mod;
}else {
f[1][1]-=1;
return (f[1][1]+Mod)%Mod;
}
}
int main(){
cin>>n;
inv2=qpow(2,Mod-2);inv3=qpow(3,Mod-2);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
cout<<((dp(0,0)+dp(1,0))%Mod-(dp(0,1)+dp(1,1))%Mod+Mod)%Mod;
}