C. Multiplicity(dp+筛选因子)

. \color{Red}Ⅰ.朴素做法

d p [ k ] k 设dp[k]为当前序列长k有多少种选法

a i , a i s 那么对于当前的a_i,筛选a_i的所有因子s

d p [ s ] + = d p [ s 1 ] dp[s]+=dp[s-1]

d p , 但是这样直接转移dp数组已经改变了,下一个因子的转移可能会出问题

t e m p n u m , 所以我们先用temp数组和num数组保存本次加多少,再一起加上去

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1000009;
ll n,a[maxn],dp[maxn];
ll temp[maxn],num[maxn],top;
int main()
{
	cin >> n;
	for(int i=1;i<=n;i++)	cin >> a[i];
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		top=0;
		for(int j=1;j<=sqrt( a[i] );j++)
		{
			if( a[i] % j != 0)	continue;
			temp[++top]=dp[j-1],num[top]=j;
			if( j*j != a[i] )	temp[++top]=dp[ a[i]/j-1],num[top]=a[i]/j;
		}
		for(int j=1;j<=top;j++)
		{
			int x=num[j];
			dp[x]=( dp[x]+temp[j] )%mod;
		}
	}
	ll ans=0;
	for(int i=1;i<=n;i++)
		ans = ( ans+dp[i] )%mod;
	cout << ans;
}

. \color{blue}Ⅱ.因子筛

前面用额外数组来辅助转移

, 实际上我们可以先从大的因子转移,再转移到小的因子

01 这样类似01背包的倒序转移就不会影响

? 但是如何获得从大到小的所有因子呢?

n = 100000 , 使 因为n=100000,所以直接使用因子筛

void init()//预先处理因子
{
    for(int i=1;i<=MAXN*10;i++)
    {
        for(int j=i;j<=MAXN*10;j+=i)
        {
            p[j].push_back(i);
        }
    }
}

然后转移的时候直接从大因子开始转移即可

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/106819184