CodeForces#523(div2) C-Multiplicity (dp)

版权声明:欢迎评论与转载,转载时请注明出处! https://blog.csdn.net/wjl_zyl_1314/article/details/84503454

原题链接:
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;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/84503454
今日推荐