Ⅰ.朴素做法
设dp[k]为当前序列长k有多少种选法
那么对于当前的ai,筛选ai的所有因子s
dp[s]+=dp[s−1]
但是这样直接转移dp数组已经改变了,下一个因子的转移可能会出问题
所以我们先用temp数组和num数组保存本次加多少,再一起加上去
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1000009;
ll n,a[maxn],dp[maxn];
ll temp[maxn],num[maxn],top;
int main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
dp[0]=1;
for(int i=1;i<=n;i++)
{
top=0;
for(int j=1;j<=sqrt( a[i] );j++)
{
if( a[i] % j != 0) continue;
temp[++top]=dp[j-1],num[top]=j;
if( j*j != a[i] ) temp[++top]=dp[ a[i]/j-1],num[top]=a[i]/j;
}
for(int j=1;j<=top;j++)
{
int x=num[j];
dp[x]=( dp[x]+temp[j] )%mod;
}
}
ll ans=0;
for(int i=1;i<=n;i++)
ans = ( ans+dp[i] )%mod;
cout << ans;
}
Ⅱ.因子筛
前面用额外数组来辅助转移
实际上我们可以先从大的因子转移,再转移到小的因子
这样类似01背包的倒序转移就不会影响
但是如何获得从大到小的所有因子呢?
因为n=100000,所以直接使用因子筛
void init()//预先处理因子
{
for(int i=1;i<=MAXN*10;i++)
{
for(int j=i;j<=MAXN*10;j+=i)
{
p[j].push_back(i);
}
}
}
然后转移的时候直接从大因子开始转移即可