[清华集训2016] 你的生命已如风中残烛
考虑我们对所有数都减一,那么我们求的就是这个每个前缀和都是大于等于0的数列数量。
那么有这么一个定理:
如果有一个数列其和为1,那么在他的循环移位上有且仅有一个满足前缀和全大于等于0
那么我们发现这个原题是和为 \(0\) ,那么我们需要找到一个可行的方案放入一个1,且其一定是循环移位的第一个数,即没有数比他大,所以我们直接取反,再把他这个1加在这个前面。
那我们考虑圆排列,那么就是\((m + 1 - 1)! = (m)!\),考虑第一个\(1\)有 \(m - n + 1\) 个,即有这个 \( (m - n + 1)!\)排列,因为是多加了一个所以其实多算了 \((m - n + 1)\)。
#include<iostream>
#include<cstdio>
#define ll long long
#define N 50
#define mod 998244353
ll num[N],m;
ll n;
int main(){
scanf("%lld",&n);
for(int i = 1;i <= n;++i)
scanf("%lld",&num[i]),m += num[i];
ll s = 1;
for(int i = 1;i <= m;++i)
if(i != (m - n + 1))
s = (s * i % mod) % mod;
std::cout<<s<<std::endl;
}