C - Multiplicity CodeForces - 1061C(因子筛+线性dp)

Multiplicity 

CodeForces - 1061C

Time limit 3000 ms Memory limit 262144 kB

Problem Description

You are given an integer array a1,a2,,an.

The array bb is called to be a subsequence of aa if it is possible to remove some elements from aa to get b.

Array b1,b2,,bk is called to be good if it is not empty and for every i (1≤i≤k) bibi is divisible by i.

Find the number of good subsequences in aa modulo 10^9+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 aa 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 aa.

The next line contains integers a1,a2,…,an (1≤ai≤10^6).

 

Output

Print exactly one integer — the number of good subsequences taken modulo 10^9+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}, {1,2}{1,2}, {2}{2}

In the second example, the possible good subsequences are: {2}{2}, {2,2}{2,2}, {2,22}{2,22}, {2,14}{2,14}, {2}{2}, {2,22}{2,22}, {2,14}{2,14}, {1}{1}, {1,22}{1,22}, {1,14}{1,14}, {22}{22}, {22,14}{22,14}, {14}{14}.

Note, that some subsequences are listed more than once, since they occur in the original array multiple times.

Solution:

首先看到这个mod 1e9+7,就勾起我不好的回忆了,费马小定理(大质数),NNT(原根),dp(线性/背包/树形/区间),矩阵快速幂

然后数据范围 10w,应该是设计个O(n)的算法吧(感觉自己已经边得很玄学了=_=!🦆)

想想可能是个线性dp。

先分析下题意吧,要组成一个子序列(相对位置保持不变,可以增删一些元素),且第i个元素a[i]可以整除i,换句话说i是a[i]的因子

然后观察下答案构成,假设有一个数X,那它仅能出现在 第因子位。

考虑dp,对于每个数依次取出,如果对答案有贡献的话,肯定回添加进答案序列的某个结尾,这个结尾肯定是因子位,也就是说它会跟因子位的前一位的数组成全新的序列(因为自己的位置是全新的位置,肯定不会跟前面的冲突,互斥直接相加),既然如此,每个数间对答案贡献即可叠加。

前i个数,因子是j(第j位),dp[i][j]=dp[i-1][j-1]( j是da[i]的因子),由于一个数会有多个因子,因子间不能冲突(只能在前面的数上累加嘛),所以要从右到左更新一个a[i]的贡献

注意下 dp[0][0]=1,都是从这里转移出来的,方向向左,一直统计ans就行咯

最后统计因子需要用类似素数筛的方法,n*log n 复杂度统计所有的数的因子

 

#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long ll;
const ll mod = 1e9 + 7;
ll dp[1000010],ans=0;
ll n;
vector<int>vf[1000010];

void init() {
    for (int i = 1; i <= 1000000; ++i) {
        for (int j = i; j <= 1000000; j += i) {
            vf[j].push_back(i);
        }
    }
}

ll cal(ll x) {
    ll tmp = 0;
    for (int i = vf[x].size()-1, now; i >=0; --i)
    {
        now = vf[x][i];
        ans=(ans+dp[now-1])%mod;
        dp[now] = (dp[now - 1] + dp[now]) % mod;
    }
    return tmp;
}

int main() {
    scanf("%lld", &n);
    init();
    ll x;
    dp[0] = 1;
    for (ll i = 1; i <= n; ++i) scanf("%lld", &x),cal(x);
    printf("%lld\n", ans);
    return 0;
}

 

 

 

posted @ 2019-02-18 20:33  SayGB  阅读(464)  评论(0编辑  收藏  举报