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;
}

浙公网安备 33010602011771号