题解 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. \]

现在将问题转化成:

  1. 如何求 \(\sum y_i\leq T\) 的方案数?
  2. 如何求 \(\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 的题解)

posted @ 2022-11-07 13:38  caijianhong  阅读(48)  评论(0编辑  收藏  举报