原题链接:
http://codeforces.com/contest/1061/problem/C
C. Multiplicity
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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.
题意:
输入一个由n个数组构成的数列,现在从其中删除一些元素(但不能删完),要求删除后形成的新数列,满足每个位置的数值都能被整除下标。问有多少种删法能够得到满足条件的数列?(删法不同,即使最终结果相同也记为两种方法)
题解:
一开始想着用dfs深搜去做,利用回溯去写,结果毫无疑问的TLE了,最后看了一下大佬的代码,发现可以用dp的思想去做。
整体思想是:
对于每一个输入的数列,计算其因子,找到他可以放的位置,那么如果添加上这一个元素的话,其方法数就等于在此元素的可以添加位置之前的方法数。设置一个cnt数组来记录在从第一个位置到第i个位置区间内的可行方法数,对于每一个输入都遍历一遍,最终将所有的cnt【】数组给加起来,求余即可。
附上AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define LL long long
const int mod=1000000000+7;
LL cnt[1000005];//用于记录第i个位置可以放置不同数的方法数
LL fac[1000005];//用于记录每一个a[i]的因子
int n,a[1000005];
int main()
{
while(~scanf("%d",&n))
{
LL ans=0;
cnt[0]=1;//初始化,每一种情况的第0位只有一种可能就是“啥都没有”
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
int tot=0;
int x;
for(x=1;x<a[i]/x;x++)//寻找因子
{
if(a[i]%x==0)
{
fac[tot++]=x;
fac[tot++]=a[i]/x;
}
}
if(a[i]%x==0&&x==a[i]/x)//如果因子相同例如(2*2=4)
fac[tot++]=x;
sort(fac,fac+tot);//排序
for(int j=tot-1;j>=0;j--)//每一个可能的位置的放法
{
cnt[fac[j]]+=cnt[fac[j]-1];//都等于之前的方法的后面加上这个因子(类似于dp思想)
cnt[fac[j]]%=mod;
}
}
for(int i=1;i<=1000000;i++)
{
ans=(ans+cnt[i])%mod;//取余
}
printf("%lld\n",ans);
}
return 0;
}
欢迎评论!