https://codeforces.com/problemset/problem/1061/C
アイデア:
dp [i] [j]:最初のiとi番目の長さがjのシーケンスの数
dp [i] [j] + = dp [i-1] [j];最初のi、および現在のiは、終了長がjのシーケンス
ですif(a [i]%j == 0)dp [ i] [j] + = dp [i-1] [j-1];
O(n ^ 2)最適化。これは、a [i]のすべての長さjが満たされているわけではなく、その除数がすべて満たされているためです。これはO(sqrt)です
次に、転送は前処理のおおよその位置から転送されます。
たとえば、係数の1つが7の場合、全長6を追加します。
寸法が圧縮されているため、01バックパックの逆の順序に似ています。
大きなものから小さなものまでの要因を列挙します。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=3e6+100;
typedef long long LL;
LL mod=1e9+7;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL dp[maxn];
vector<LL>v[maxn];
void solve(LL id,LL num){///求num的所有因子(非质因子)
for(LL i=1;i<=sqrt(num);i++){
if(num%i==0){
if(i*i==num){
v[id].push_back(i);break;
}
else{
v[id].push_back(i);
v[id].push_back(num/i);
}
}
}
sort(v[id].begin(),v[id].end());
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n;cin>>n;
for(LL i=1;i<=n;i++){
LL x;cin>>x;
solve(i,x);
}
///dp[i][j]+=dp[i-1][j]; 前i个,且当前i为终点长度为j的序列
///if(a[i]%j==0) dp[i][j]+=dp[i-1][j-1];
dp[0]=1;
for(LL i=1;i<=n;i++){
for(LL j=v[i].size()-1;j>=0;j--){
dp[v[i][j]]=(dp[v[i][j]]%mod+dp[v[i][j]-1]%mod)%mod;
}
}
LL ans=0;
for(LL j=1;j<=n;j++){
ans=(ans%mod+dp[j]%mod)%mod;
}
cout<<ans<<"\n";
return 0;
}