题解:AT_abc132_f [ABC132F] Small Products
思路
首先考虑一个暴力的 DP,我们用 \(dp_{i,j}\) 表示长度为 \(i\),结尾为 \(j\) 时的方案数,
动态转移方程为:
就算加个前缀和优化,时间复杂度也为 \(\mathcal{O}(nk)\),显然过不了,怎么办呢?
注意到 \(dp_{i,j_1}\) 和 \(dp_{i,j_2}\) 在 \(\lfloor \frac{n}{j_1} \rfloor = \lfloor \frac{n}{j_2} \rfloor\) 时是相等的,
不妨将他们放在一起算。
我们先用整除分块处理出 \(n\) 作为被除数,且除数不超过 \(n\) 的所有的商(此处指带余数除法的商,下文亦然),用 \(s_i\) 表示第 \(i\) 小的那个商,个数设为 \(sd\)。同时处理出其对应的除数的个数,用 \(g_i\) 表示。
则状态优化为 \(dp_{i,j}\),\(i\) 仍为长度,\(j\) 为 \(n\) 除以序列最后值的商。
先不急着求状态转移方程,我们先证一个引理:对于所有 \(i \in [1,sd]\),有:
易证对于 \(i \in [1,sd]\),有:
从整除分块的过程中观察,这是显而易见的,不再赘述。
可以确定对于 \(s_1\) 和 \(s_{sd}\) 有:
和
因为 \(s_1\) 一定为一,\(s_{sd}\) 一定为 \(n\)。
需要先解释一下的是,对于 \(i \in [1,sd]\),一定有某个 \(j \in [1,sd]\) 满足
\(\lfloor \frac{n}{s_i} \rfloor=s_{j}\)。因为 \(\lfloor \frac{n}{s_i} \rfloor\) 也是 \(n\) 作为某个被除数的一个商,一定包含在 \(s\) 中。
假设对于 \(i\) 已知 \(j\),使得 \(\lfloor \frac{n}{s_{j}}\rfloor=s_i\),则 \(\lfloor \frac{n}{s_{i}} \rfloor=s_j\)。
设 \(x\) 使得 \(\lfloor \frac{n}{s_{i+1}} \rfloor=s_{x}\),则\(\lfloor \frac{n}{s_{x}} \rfloor=s_{i+1}\)。
先证 \(x<j\):
因为
同时
所以 \(s_x<s_j\),即 \(x<j\)。
然后我们采用反证法,假设 \(x<j-1\)。
考虑 \(\lfloor \frac{n}{s_{j-1}} \rfloor\) 在 \(s\) 中的位置,先设其为 \(k\)。
因为
所以有
结合上面的 \(\lfloor \frac{n}{\lfloor\frac{n}{s_i}\rfloor}\rfloor=s_i\),
当 \(\lfloor \frac{n}{s_{j}} \rfloor=\lfloor \frac{n}{s_{j-1}} \rfloor\) 或 \(\lfloor \frac{n}{s_{j-1}} \rfloor=\lfloor \frac{n}{s_{x}} \rfloor\) 时,一定有 \(j=j-1\) 或 \(j-1=x\),与前面矛盾。
所以
也就是
显然不存在这样的 \(k\),同时有 \(x<j\),所以
所以当 \(\lfloor \frac{n}{s_{i}} \rfloor=s_j\) 时,有:
现在我们已经确定了 \(\lfloor \frac{n}{s_{1}} \rfloor=s_{sd}\)
进而有
故引理得证。
现在我们就可以写出状态转移方程了:
对于 \(i\in[1,k],j\in[1,sd]\)
再加个前缀和优化,时间复杂度为 \(\mathcal{O}(k\sqrt{n})\)。
代码
#include<iostream>
#include<cstdio>
#include<map>
#define ll long long
#define mod 1000000007
using namespace std;
ll cs[100005],cd,cg[100005],n,k,dp[105][100005];
int main(){
scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n;i++){
cs[++cd]=n/i;
ll ni=n/(n/i);
cg[cd]=ni-i+1;
i=ni;
}
for(ll i=1;i<=cd;i++){
dp[1][i]=cg[i];
}
for(ll i=2;i<=k;i++){
ll qz=0,d=0;
for(ll j=cd;j>=1;j--){
d++;
qz+=dp[i-1][d];
qz%=mod;
dp[i][j]=qz*cg[j];
dp[i][j]%=mod;
}
}
ll ans=0;
for(ll i=1;i<=cd;i++){
ans+=dp[k][i];
ans%=mod;
}
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号