海亮OJ庆生赛题解(福星)

这篇博客主要解析了海亮OJ庆生赛中的一道题目《福星》,探讨了如何使用贪心算法和一种称为“反向筛”的优化技巧来解决这个问题。由于原始题目数据规模大,暴力求解会导致超时,博主通过反向筛的方法减少了时间复杂度,但初次提交仍有部分点超时。通过对输入输出方式的调整以及进一步优化,最终实现了AC(Accepted)的代码解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

海亮OJ庆生赛题解(福星)

刘老师生日=庆生赛???这次比赛的题目都比较虚伪。没有稳拿的水题QAQ所以就要用贪心算法----挑简单的做。

首先是第三题《福星》,简单说一下题目描述:

每个人都有一个号码,如果第 i个人的幸运号码能被第 j个人的幸运号码整除, 那么第 j 个人就是第 i个人的福星。自己当然不能是自己的福星。

求每个人有多少个福星。。。

思路:题目意思就是求每个数能被多少个数整除,显然用暴力是肯定行不通的,应为数据实在是太大了。所以就要想到如何进行优化,减少时间复杂度。然后首先我就立马想到了素数筛法(详细代码见黑皮书P174页),素数筛法是把每个素数的被数都筛一遍。这题思路其实也可以想成刚好相反的算法,把合数“筛”一遍(筛法当然不同)。暂且把这种思路称为“反向筛”。然后用这种思路把每个数筛一遍,最后输出,但是也还要考虑很多细节(不然也不会就这么点分了QAQ)。这种反向筛具体思路见代码。

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,a[1000001]={},b[1000001]={},c[1000001]={};
int main()
{
	cin>>n;
    for(i=1;i<=n;i++)
	{
		cin>>a[i]; b[a[i]]++;
		if(a[i]>m) m=a[i];
	}
	for(i=1;i<=m;i++)
    if(b[i]>0) for(j=i;j<=m;j+=i) c[j]+=b[i];
	for(i=1;i<=n;i++) cout<<c[a[i]]-1<<endl;
	return 0;
}

这样”反向筛“的算法应该是没有问题了,但提交上去显然会发现只拿到了部分分,剩下的最后几个点全部是超时!?

现在就要处理具体细节了,既然是超时,就一定要调整部分数组,然后因为数据太大,所以要改成scanf和printf。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m=0,i,j,a[100010]={},b[1000100]={},c[1000100]={};
int main()
{
	cin>>n;
    for(i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[a[i]]++;
		if(a[i]>m) m=a[i];
	}
	for(i=1;i<=m;i++)
    if(b[i]>0) for(j=i;j<=m;j+=i) c[j]+=b[i];
	for(i=1;i<=n;i++) printf("%d\n",c[a[i]]-1);
	return 0;
}

但程序还可以有一定优化,这是别人的优化代码:

#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int a[1000010]={},b[1000010]={},c[1000010]={};
int main()
{
	int n,m;
	cin>>n;
	int Max=-1;
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[a[i]]++;
		if (a[i]>Max) Max=a[i];
	}
	for(int i=1;i<=Max;i++)
	 {
	 	if (b[i]>0)
	 	 	for(int j=i;j<=Max;j=j+i)
	 	 	 	c[j]=c[j]+b[i];
	 }
	for(int i=1;i<=n;i++)
	 	printf("%d\n",c[a[i]]-1);
	return 0;
}
看完了别人的代码,就知道自己还有很多不足,还要多刷题练手速QAQ
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值