Multiplicity

题解
\(dp[i][j]\):用了\(i\)个数序号是\(j\)的方案数。
\[dp[i][j] = \begin{cases}
dp[i - 1][j] + dp[i - 1][j - 1] & (a[i] \% j == 0)\\
dp[i - 1][j] \\
\end{cases}
\]
因为\(dp[i][j]\)只和\(i - 1\)的状态有关,所以可以用滚动数组优化。另外,观察发现,\(dp[i][j]\)的更新当且仅当\(a[i] \% j == 0\),预处理\(a[i]\)的约数,在用背包的优化思路,可以做到\(O(nsqrt(max(a_i)))\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
const int mod = 1000000007;
int n;
int a[N], cnt[N * 10];
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
cnt[0] = 1;
for (int i = 1; i <= n; ++i) {
vector<int> t;
for (int j = 1; j * j <= a[i]; ++j) if (a[i] % j == 0) {
t.push_back(j);
if (a[i] != j * j) t.push_back(a[i] / j);
}
sort(t.begin(), t.end());
reverse(t.begin(), t.end());
for (auto &it: t) {
cnt[it] += cnt[it- 1];
cnt[it] %= mod;
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
ans += cnt[i];
ans %= mod;
}
cout << ans;
return 0;
}

浙公网安备 33010602011771号