Multiplicity
我们可以先
n
l
o
g
n
nlogn
nlogn 预处理出所有数的约数。我们首先用
d
p
[
i
]
dp[i]
dp[i] 表示当前长度为
i
i
i 的子序列有多少个。那么我们首先设
d
p
[
0
]
=
1
dp[0]=1
dp[0]=1 ,我们可以认为空串是符合条件的,待会不统计就是。然后我们依次遍历每个数,去遍历其约数
d
d
d ,每个约数就代表其可以放的位置,那么其前面就一定要放长度为
d
−
1
d-1
d−1 的序列,且只要是长度为
d
−
1
d-1
d−1 就都可以放,那么我们
d
p
[
i
]
dp[i]
dp[i] 已经记录了某长度的符合条件的子序列个数,所以我们加上
d
p
[
d
−
1
]
dp[d-1]
dp[d−1] 即可,但记住不要在遍历的时候加,因为这样会改变本身的
d
p
dp
dp ,可能会对后面造成影响。所以,记录一下再加即可,最后答案即是
∑
i
=
1
n
d
p
[
i
]
\sum\limits_{i=1}^{n}dp[i]
i=1∑ndp[i]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
int n, a[N];
ll dp[N];
vector<int> g[N];
vector<int> add;
void init(int n) {
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
g[j].push_back(i);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
init(1000000);
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
add.clear();
for (auto d : g[a[i]]) {
add.push_back(dp[d - 1]);
}
for (int j = 0; j < (int)add.size(); ++j) {
int d = g[a[i]][j];
dp[d] = (dp[d] + add[j]) % mod;
}
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
ans = (ans + dp[i]) % mod;
}
printf("%lld", ans);
}