codeforces 1061 C. Multiplicity(dp)

C. Multiplicity
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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.

思路:看到题目想到是dp,但具体写不出来…
N为1e5,只能开一维的dp,dp[i],表示当前数为b数组中第i个数的总数,可以得到转移方程,dp[1]=dp[1]+1,dp[i]=dp[i-1]+dp[i],这里应该是表示之前的dp[i-1]的状态转移到现在的dp[i],所以我们应该从大因子从大往小循环,如果从小到大就会产生影响到大的状态,和01背包原理类似。
为减小时间复杂度,首先将每个数的因子分解出来,从大到小,如果因子小于等于当前i才更新,然后将以每一个数目结尾的状态求和。

#include<bits/stdc++.h>
#define fi first
#define se second
#define FOR(a) for(int i=0;i<a;i++)
#define sc(a) scanf("%d",&a)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 1e6 + 10;
const ll mod = 1e9+7;

map<string, int>ml;



ll c[N], vis[N],  num[N], t, n, m, x, y, k, a[N],sum;
char s[N];
ll ex, ey, cnt, ans;
ll dist[N];
ll dp[N];
deque <int> q;
map<int,int> mp;
vector<int> v[N];

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);

	for(int i=1;i<N;i++)
	{
		if(!vis[i])
		{
			for(int j=i;j<N;j+=i)
			{
				v[j].push_back(i);

			}
			vis[i]=1;
		}
	}

	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=v[a[i]].size()-1;j>=0;j--)
		{
			t=v[a[i]][j];
			if(t<=i)
			{
				if(t==1) dp[t]=(dp[t]+1)%mod;
				else dp[t]=(dp[t]+dp[t-1])%mod;
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		ans=(ans+dp[i])%mod;
	}
	cout<<ans<<endl;



}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值