CF1188E Problem from Red Panda【分析性質,計數】
阿新 • • 發佈:2021-06-22
給定長為 \(n\) 的自然數序列 \(a_1,\cdots,a_n\),任意次操作選擇 \(i\in[1,n]\),若 \(\forall j\ne i,a_j>0\) 則令 \(\forall j\ne i,a_j:=a_j-1\),\(a_i:=a_i+n-1\)。
求能得到的序列 \(a\) 數量\(\bmod 998244353\)。
\(n\le 10^5\),\(a_i\le 10^6\)。
設 \(x_i\) 表示對 \(i\) 的操作次數,\(s=\sum x_i\),則一個必要條件是 \(x_i\ge\lceil\frac{s-a_i}n\rceil\)。
它充分麼?其實不是,比如 \(0,\cdots,0,n\)
於是還有條件:\(\forall t\in[0,s)\) 滿足 \(t\) 次操作之後 \(a\) 非負,則有 \(\sum_{i=1}^n\lceil\frac{\max(t-a_i,0)}n\rceil\le t\)。
它充分麼?感性理解一下是的
數 \(x\) 就可以了麼?最後的 \(a_i'=a_i+nx_i-s\),則 \(x_i\) 都不為 \(0\) 時,令所有 \(x_i:=x_i-1\) 時得到的方案等價。
數 \(\min x=0\) 的 \(x\) 就可以了麼?理性理解一下是的
此時 \(s\le\max a_i\),所以直接從小到大列舉 \(s\),開桶維護 \(a_i\bmod n\)
時間複雜度 \(O(\text{Sorting}(n)+\max a_i)\)。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 1e5+3, M = 1100003, mod = 998244353; template<typename T> void rd(T &x){ int ch = getchar(); x = 0; for(;ch < '0' || ch > '9';ch = getchar()); for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0'; } int n, ans, a[N], cnt[N], fac[M], inv[M]; int ksm(int a, int b){ int r = 1; for(;b;b >>= 1, a = (LL)a * a % mod) if(b & 1) r = (LL)r * a % mod; return r; } void qmo(int &x){x += x >> 31 & mod;} int main(){ rd(n); fac[0] = 1; for(int i = 0;i < n;++ i) rd(a[i]); sort(a, a+n); for(int i = 1;i < M;++ i) fac[i] = (LL)fac[i-1] * i % mod; inv[M-1] = ksm(fac[M-1], mod-2); for(int i = M-1;i;-- i) inv[i-1] = (LL)inv[i] * i % mod; for(int i = 0, j = 0, now = 0;i <= a[n-1];++ i){ while(j < n && a[j] < i) ++cnt[a[j++]%n]; if((now += cnt[(i+n-1)%n]) > i) break; ans = (ans + (LL)fac[i-now+n-1]*inv[i-now]) % mod; if(i+j>=now+n) qmo(ans -= (LL)fac[i-now+j-1]*inv[i-now+j-n]%mod); } printf("%lld\n", (LL)ans*inv[n-1]%mod); }