Codeforces Round #523 (Div. 2) C. Multiplicity (dp)

C. Multiplicity

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given an integer array ?1,?2,…,??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 ?1,?2,…,??b1,b2,…,bk is called to be good if it is not empty and for every ?i (1≤?≤?1≤i≤k) ??bi is divisible by ?i.

Find the number of good subsequences in ?a 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 ?a has exactly 2?−12n−1 different subsequences (excluding an empty subsequence).

Input

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

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

Output

Print exactly one integer — the number of good subsequences taken modulo 109+7109+7.

Examples

input

Copy

2
1 2

output

Copy

3

input

Copy

5
2 2 1 22 14

output

Copy

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.

解决思路:

用dp解决,怎么想到的?不知道。这种计数的题大多都用dp,我只能这样告诉你(我是想到了,但没有想出来)。

会先想到用二维dp来解决,用dp[i][j]代表前i个数构成长度为j的b数组的方案数目,那么状态转移方程为:

dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1]           其中j为i的约数

思路完全没问题,但是仔细想一想空间好像不够诶,然后发现求dp[i][j]的时候用到的都是dp[i - 1]的状态,考虑用滚动数组优化,这都是常规套路。。优化完之后的方程为:

dp[j] = dp[j] + dp[j - 1]       

代码还是比较简单的,好好理解一下。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

typedef long long ll;
const int maxn = 1e5 + 1;
const int mod = 1e9 + 7;

int val[maxn];
ll dp[maxn];
vector < int > facter[maxn * 10];


void Init()
{
	for(int i = 1; i <= maxn * 10; ++ i)
	{
		for(int j = i; j <= maxn * 10; j += i)
		{
			facter[j].push_back(i);
		}
	}
}

int main()
{
	//freopen("in.txt", "r", stdin);
	int n;
	cin >> n;
	Init();
	for(int i = 1; i <= n; ++ i)
	{
		scanf("%d", &val[i]);
	}
	for(int i = 1; i <= n; ++ i)
	{
		for(int j = (int)facter[val[i]].size() - 1; j >= 0; -- j)
		{
  			int t = facter[val[i]][j];
			if(t > i)    //如果t比i大是没有意义的,因为前i个数不可能构成长度为t的b数组
				continue;
			if(t == 1)
				dp[1] = (dp[1] + 1) % mod;
			else 
				dp[t] = (dp[t] + dp[t - 1]) % mod;
		}
	}
	ll ans = 0;
	for(int i = 1; i <= n; ++ i)
	{
		ans = (ans + dp[i]) % mod;
	}
	cout << ans << endl;
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值