『动态规划』Multiplicity

题目描述

在这里插入图片描述

题解

由于又是整除的题,我们便只能够从整除的特性上去考虑这一个问题了。

可以证明,一个数的因数不超过 n \sqrt n n 个,这意味着我们可以在因数上做文章。

f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i个数,放在第 j j j个位置的方案数。对于当前数的每一个因数 x x x,有:
f [ i ] [ x ] + = f [ i − 1 ] [ x − 1 ] f[i][x]+=f[i-1][x-1] f[i][x]+=f[i1][x1]
由于 i i i i − 1 i-1 i1有关,我们可以使用滚动数组;由于 i i i i − 1 i-1 i1转移的时候如果不是因数要每一个状态都向 i − 1 i-1 i1转移,所以我们一定要使用滚动数组进行处理。

每次可以将因数排序,从大到小转移即可。

所以遇见 g c d gcd gcd的题就一定要想到分解质因数,遇到整除的题一定要想到分解因数。

时间复杂度: O ( n n ) . O(n\sqrt n). O(nn ).

#include <bits/stdc++.h>

using namespace std;
const int N = 2000000;

int n, ans = 0, m = 0;
int a[N], f[N], b[N];

const int P = 1e9+7;

int main(void)
{
	scanf("%d", &n);
	for (int i=1;i<=n;++i)
		scanf("%d", a+i);
	f[0] = 1;
	for (int i=1;i<=n;++i)
	{
		m = 0;
		for (int j=1;j*j<=a[i];++j)
		{
			if (a[i] % j == 0) 
				b[++m] = j;
			if (a[i] % j == 0 && j * j ^ a[i])
			    b[++m] = a[i]/j;
		}
		sort(b+1,b+m+1);
		reverse(b+1,b+m+1);
		for (int i=1;i<=m;++i) 
			f[b[i]] = (f[b[i]]+f[b[i]-1]) % P;
	} 
	for (int i=1;i<=1e6;++i) 
		ans = (ans+f[i]) % P;
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值