2020ICPC·小米 网络选拔赛第一场 A. Intelligent Warehouse

在这里插入图片描述
题意:给你一组数然后统计他们之中能组成两两互为倍数的数最多有多少个?

思路:考虑DP,dp[i]代表值当前选的数都为i的约数的最大的个数是多少,我们当然可以暴力的用每个i去更新它的倍数,但是这样做会超时,我们可以用素数去更新它的倍数,素数筛的优化一样,省去很多不必要的更新,然后每次取下max就是答案了。
dp[i]的初始化为i这个数在原序列中出现的次数。

素数问题做少了,还要多练习数学思维啊

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e7 + 7;
int prime[MAXN],vis[MAXN],cnt;

void work(){
	for(int i = 2;i < MAXN;i ++){
		if(!vis[i]) prime[++cnt] = i;
		for(int j = 1;j <= cnt && prime[j] * i < MAXN;j ++){
			vis[prime[j]*i] = 1;
			if(i % prime[j] == 0)
				break;
		}
	}
}

int dp[MAXN],num[MAXN];

int main()
{
	work();
	int n,x;
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++){
		scanf("%d",&x);
		num[x]++;
	}
	int ans = 0;
	for(int i = 1;i < MAXN;i ++){
		dp[i] += num[i];
		ans = max(ans,dp[i]);
		for(int j = 1;j <= cnt && prime[j] * i < MAXN;j ++){
			dp[prime[j]*i] = max(dp[prime[j]*i],dp[i]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值