C. Multiplicity(思维+dp优化)
作者:互联网
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)
于是转移从其预处理的约数位置转移过来。
比如其中一个因数是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;
}
标签:思维,Multiplicity,LL,因子,长度,include,dp,mod 来源: https://blog.csdn.net/zstuyyyyccccbbbb/article/details/114680488