【动态规划专练-线性DP】CF1061C (1700)
Multiplicity
You are given an integer array a1,a2,…,an.
The array b is called to be a subsequence of a if it is possible to remove some elements from a to get b.
Array b1,b2,…,bk is called to be good if it is not empty and for every i (1≤i≤k) bi is divisible by i.
Find the number of good subsequences in a modulo 109+7.
Two subsequences are considered different if index sets of numbers included in them are different. That is, the values of the elements do not matter in the comparison of subsequences. In particular, the array a has exactly 2n−1 different subsequences (excluding an empty subsequence).
Input
The first line contains an integer n (1≤n≤100000) — the length of the array a.
The next line contains integers a1,a2,…,an (1≤ai≤106).
Output
Print exactly one integer — the number of good subsequences taken modulo 109+7.
Examples
Input
2
1 2
Output
3
Input
5
2 2 1 22 14
Output
13
Note
In the first example, all three non-empty possible subsequences are good: {1}, {1,2}, {2}
In the second example, the possible good subsequences are: {2}, {2,2}, {2,22}, {2,14}, {2}, {2,22}, {2,14}, {1}, {1,22}, {1,14}, {22}, {22,14}, {14}.
Note, that some subsequences are listed more than once, since they occur in the original array multiple times.
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <stack>
#include <cstdio>
#include <queue>
#include <set>
#include<sstream>
#include <cstring>
#include <cmath>
#include <bitset>
//#pragma GCC optimize(2);
#define IOS ios::sync_with_stdio(false);
#define mm(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
typedef long long ll;
const int N = 1e6+5;
const int M = N*2;
const double eps =1e-8;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double maxd = -1e9;
const int maxn = 500;
using namespace std;
typedef pair<int,int> PII;
//状态,阶段,决策
//把最后一个阶段独立出来,又要让它有方式由之前的状态转移而来
//怎么转移? 依据题目规则转移
//对这道题,长序列可以由短序列转移而来,所以必有一维是当前序列位
//考虑f[i]怎么由前f[i-1]个阶段转移到:
//根据题目规则:前面的子序列大小为j加上最后一个f[i](j|f[i])组成了一个答案
//状态就好表示了:f[i][j]:到第i位,子序列大小为j的方案数
//转移方程:f[i][j] = f[i-1][j] + f[i-1][j-1] | a[i]%j==0 , f[i][j] = f[i-1][j] | a[i]%j!=0 ;
//转移顺序 i:1->n j:0->n
//边界情况 f[0][0] = 1 ;
//空间爆了,傻逼
//考虑滚动数组优化,每一行要倒推
//a[i]的数值比较小,还可以先处理出来每个bi的除数
bool cmp(int a,int b){
return a>b;
}
int a[N];int f[N]; vector<int>ve;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
f[0] = 1;
for(int i=1;i<=n;i++){
ve.clear();
for(int j=1;j<=a[i]/j;j++){
if(!(a[i]%j)){
ve.push_back(j);
if(a[i]/j!=j) ve.push_back(a[i]/j);
}
}
sort(ve.begin(),ve.end(),cmp);
for( auto j :ve){
f[j] = (f[j]+f[j-1])%mod;
}
}
ll ans = 0;
for(int i=1;i<=n;i++){
ans+=f[i];
ans%=mod;
}
cout<<ans<<endl;
return 0;
}