Solution - P3861 拆分

一道题咕了五天才咕出来……

思路

定义状态 \(dp_{i,j}\) 为咕到第 \(i\) 个因数且最大因子为 \(j\) 的方案数量。

易得方程式:

\[dp_{i,j} = \begin{cases} dp_{i,j-1}+dp_{\frac{i}{j}, j-1} & \text{if } i \mid j \\ dp_{i,j-1} & \text{otherwise.} \end{cases} \]

然后离散化一下,没了。不理解 luogu 题解区用根号分治意义何在。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define SIZ 10005
using namespace std;

constexpr llong mod = 998244353;
llong rec[SIZ], cnt;
llong dp[SIZ][SIZ];
llong n;

int _main(){
	scanf("%lld", &n), cnt = 0;
	for(rint i = 1; 1ll*i*i <= n; ++i){
		if(n % i) continue;
		rec[++cnt] = i;
		if(i*i != n) rec[++cnt] = n/i;
	}
	sort(rec+1, rec+cnt+1);
	dp[1][1] = 1;
	for(rint i = 1; i <= cnt; ++i){
		for(rint j = 2; j <= cnt; ++j){
			rllong val = dp[i][j-1];
			if(rec[i] % rec[j] == 0)
				val += dp[lower_bound(rec+1, rec+cnt+1, rec[i]/rec[j])-rec][j-1];
			dp[i][j] = val%mod;
		}
	}
	printf("%lld\n", (dp[cnt][cnt]-1+mod)%mod);
	return 0;
}

int t;
int main(){
	scanf("%d", &t);
	while(t--) _main();
	return 0;
}

posted @ 2025-05-05 09:58  Hootime  阅读(12)  评论(0)    收藏  举报