【动态规划专练-线性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;
}
posted @ 2021-09-10 09:20  qingyanng  阅读(65)  评论(0编辑  收藏  举报