专栏文章

题解:P11126 [ROIR 2024] 三等分的数组 (Day 2)

P11126题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minlsnkc
此快照首次捕获于
2025/12/02 04:30
3 个月前
此快照最后确认于
2025/12/02 04:30
3 个月前
查看原文
要想到上界 O(m3)O(m^3) 的 dp 是简单的,重点在于复杂度分析。
dpi,j,kdp_{i,j,k} 表示当前考虑到值为 ii 的数字,当前数字剩余 jj 个,上一个数字剩余 kk 个的方案数。容易有转移:
dpi,j,kdpi+1,ai+1x,jx,3kxdp_{i,j,k}\to dp_{i+1,a_{i+1}-x,j-x},3\mid k-x
滚动数组加枚举 jj,倒序枚举 xx 即可做到一个上界 O(m3)O(m^3) 的 dp。
由于数的总个数和 mm 同阶,也许我们认为的上界会很松。
仔细分析一下,时间复杂度的贡献应该是 i=1mcnti1×cnti\sum_{i=1}^{m} cnt_{i-1}\times cnt_{i} 的,有 (a+b)2a2+b22ab(a+b)^2\ge a^2+b^2\ge 2ab,所以上界应是 (i=0mcnti)2=n2\left(\sum_{i=0}^{m}cnt_i\right)^2=n^2
CPP
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*f;
}
bool mbs;
#define ll long long
const int mod=1e9+7;
const int maxn=5e3+20;
ll sum[4],dp[2][maxn][maxn],n,a[maxn],m;
bool mbt;
int main(){
//	cerr<<(&mbs-&mbt)/1024.0/1024.0<<endl;
	n=read(),m=read();int x;
	for(int i=1;i<=n;i++) x=read(),a[x]++;
	dp[0][0][0]=1;
	for(int i=0;i<m;i++){
		int cur=(i&1);
		for(int j=0;j<=a[i];j++) for(int k=0;k<=a[i+1];k++) dp[cur^1][k][j]=0;
		for(int j=0;j<=a[i];j++){
			sum[0]=sum[1]=sum[2]=0;
			for(int x=(i==0?0:a[i-1]);x>=0;x--){
				sum[x%3]=(sum[x%3]+dp[cur][j][x])%mod;
				if(x<=min<ll>(j,a[i+1])) dp[cur^1][a[i+1]-x][j-x]=(dp[cur^1][a[i+1]-x][j-x]+sum[x%3])%mod;
			}
		}
	}
	ll ans=0;
	for(int i=0;i<=a[m-1];i++) for(int j=0;j<=a[m];j++) if(i%3==0&&j%3==0) ans=(ans+dp[m&1][j][i])%mod;
	printf("%lld\n",ans); 
	return 0;
}
/*
3 1
1 1 1
*/

评论

0 条评论,欢迎与作者交流。

正在加载评论...