题解 ABC276G【Count Sequences】
problem
求有多少个单调递增的整数数列,使得相邻两项对三取模的余数不相同。值域为 \([0,m]\),长度为 \(n\)。\(n,m\leq 10^7\)。
solution
考虑差分数组 \(b_i=a_i-a_{i-1}\),将问题转换成:
- \(b_1\geq 0\).
- \(b_i>0\quad(i>1)\).
- \(\sum b_i\leq M\).
考虑将 \(b_i\) 表示为 \(3y_i+x_i\) 之形式,其中 \(x_i<3\),显然 \(x_i,y_i\) 是独立的,只要满足和的限制就好。具体地,限制为
\[\sum y_i\leq \left\lfloor\frac{M-\sum x_i}{3}\right\rfloor.
\]
现在将问题转化成:
- 如何求 \(\sum y_i\leq T\) 的方案数?
- 如何求 \(\sum x_i\leq T\) 的方案数?
task 1
在所有 \(y_i\) 加一后,变成这样一个问题:
- 已知 \(\sum y_i\) 且 \(y_i\geq 1\),求有多少种分配的方案?
显然这是隔板法,那么 \(\sum y_i=T\) 的方案数为 \(\binom{T+n-1}{n-1}\),做个前缀和预处理即可。
task 2
观察到除了 \(x_1\) 外每个 \(x_i\) 的取值都是 \(1\) 或 \(2\),那么我直接枚举有多少个 \(1\) 即可。对于 \(x_1\) 它也只有三种取值。
复杂度线性。
code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int P=998244353;
const int N=2e7;
int n,m;
LL qpow(LL a,LL b,int p=P){LL r=1;for(a%=P;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p; return r;}
LL fac[N+10],ifac[N+10],s[N+10],ans;
LL C(int n,int m){return fac[n]*ifac[m]%P*ifac[n-m]%P;}
int main(){
for(int i=fac[0]=ifac[0]=1;i<=N;i++) fac[i]=fac[i-1]*i%P;
ifac[N]=qpow(fac[N],P-2);
for(int i=N-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%P;
scanf("%d%d",&n,&m);
s[0]=1;
for(int i=1;i<=m;i++) s[i]=(s[i-1]+C(n+i-1,n-1))%P;//,printf("s[%d]=%lld\n",i,C(n+i-1,n-1));
for(int x0=0;x0<=2;x0++){
for(int i=0;m>=n+i-1+x0&&n-1>=i;i++){
//sum x_i=2i+n-1-i+x0=n+i-1+x0
//numbers of x_i=C(n-1,i)
//sum y_i<=(m-sum x_i)/3
int sumx=n+i-1+x0;
ans=(ans+C(n-1,i)*s[(m-sumx)/3])%P;
}
}
printf("%lld\n",ans);
return 0;
}
review
\(\sum y_i\leq T\) 的方案数为 \(\binom{T+n}{n}\)。因为我们有 \(\sum_{0\leq i\leq n}\binom{i+m}{m}=\binom{n+m+1}{m+1}\)。(参考 ABC154F 的题解)
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/solution-abc276g.html