Codeforces Round #523 (Div. 2) C Multiplicity (DP+动态数组)

Multiplicity

time limit per test   3 seconds

memory limit per test  256 megabytes

You are given an integer array a1,a2,…,ana1,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 bb.

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

Find the number of good subsequences in aa modulo 109+7109+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−12n−1 different subsequences (excluding an empty subsequence).

Input

The first line contains an integer nn (1≤n≤1000001≤n≤100000) — the length of the array aa.

The next line contains integers a1,a2,…,ana1,a2,…,an (1≤ai≤1061≤ai≤106).

Output

Print exactly one integer — the number of good subsequences taken modulo 109+7109+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.

 

题目大意:给你n个数,a1,a2...an。你可以通过删除若干个元素来构成一个新的序列,b1,b2...bk。如果对于b序列的每一个数都有bi / i 能整除,则称b序列为good。问你有多少种不同的b序列,输出结果模1e9+7;

解题思路:动态规划。如果定义一个dp[maxn][maxn]数组,dp[i][j]表示第i个数字(a[i])前可以得到的长度为j的b序列情况数。

dp方程为  dp[i][j]=(dp[i-1][j]+dp[i-1][j-1])%mod。但是这题n最大是1e5,二维数组开不了,所以考虑用一维数组滚动更新。

就是dp[maxn],对于每一次更新,dp[i]=(dp[i]+dp[i-1])%mod。

本题还需要定义动态数组,保存a序列里的每一个元素的因子(包括1和它本身)。用动态数组的原因是动态数组可以调节大小,不会占用不必要的内存,防止内存超限。

dp方程不是很难想,我认为这题最大的难点 是在于判断序列的当前元素是否可以放在b序列的第j个位置上。

ps:感觉直接求因子的方法很暴力,第一次看到这种方法时,感觉像是打开了新世界的大门,哈哈(原来还这样也可以)。

 

下面附上代码:

#define cin0  ios::sync_with_stdio(0),cin.tie(0);
#define ull unsigned long long 
#define inf 0x3f3f3f3f
#define ll long long 
#include <algorithm>
#include <iostream>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <bitset>
#include <vector>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
using namespace std;
const int man=1e5+50;
const ll mod=1000000007;
vector<int>a[man];
ll dp[man*10];
int main() 
{
	int n,m;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>m;
		for(int j=1;j<=sqrt(m);j++){
			if(m%j==0){
				a[i].push_back(j);
				if(j*j!=m)
					a[i].push_back(m/j);
			}
		}
		sort(a[i].begin(),a[i].end());
	}
	dp[0]=1;
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=a[i].size()-1;j>=0;j--){
			dp[a[i][j]]=(dp[a[i][j]-1]+dp[a[i][j]])%mod;
			ans=(ans+dp[a[i][j]-1])%mod;//ans等到全部更新完再加也可以
		}
	}
	cout<<ans<<endl;
    return 0;
}

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值