2020寒假【gmoj2092】【game】【埃氏筛】

题目描述

Guyu Guo和Tube Lu正在玩一个游戏:Lu默想一个1和n 之间的数x,然后Guo尝试猜出这个数。
Guo能提出m个这样的问题: “未知数是否能被yi整除?”
游戏按照如下流程进行:Guo先给出他想问的全部m个问题,然后Lu对所有问题依次以“是”或“否”作答。得到m个问题的答案之后,Guo就要给出他的猜测。
Guo写了一个程序帮他以最优的方式提出这m个问题,现在他想知道在保证得到一个确定的答案下,最少可以问多少个问题,即m的最小值。

输入

一行,一个整数n

输出

一行,一个整数m(表示最少问m个问题)

样例输入

【样例输入1】
4

【样例输入2】
8

样例输出

【样例输出1】
3

【样例输出2】
6

样例1解释:
Guo依次提问能否被2,3,4整除,就可以得到确定答案。
比如Lu回答能被2,4整除,不能被3整除,则确定答案为4
样例2解释:
Guo依次提问能否被2,3,4,5,7,8整除,总共需要6次。

分析

其实这题我一开始看到完全是懵逼的,样例都看不懂。
经过ymw大佬的指点,我恍然大悟。。。

我们可以发现一个规律:要问的数就是小于等于n的k^p。k是质数,p是正整数。

ymw大佬还指出:这种题一般都是猜结论然后证明,可以手推几个小样例。
至于这个规律怎么证明,我也没太懂,放几张截图大伙看看:在这里插入图片描述
在这里插入图片描述
这时我写了一篇代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a[100001]={0},s[100001]={0};
long long ans,sum;
int pdzs(int x)
{
	int p=0;
	for(register int k=2;k<=x-1;k++)
	{
		if(x%k==0)
		{
			return 0;
		}
	}
	return 1;
}
int main()
{
//	freopen("game.in","r",stdin);
//	freopen("game.out","w",stdout);
	cin>>n;
	for(register int i=2;i<=n;i++)
	{
		if(pdzs(i)==0) continue;
		else
		{
			for(register int j=1;j<=n;j++)
			{
				sum=pow(double(i),double(j));
				if(sum<=n&&a[sum]==0)
				{
					
					ans++;
					a[sum]=1;	
				}
				else break;
			}
		}
	}
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
    return 0;
}

结果超时了。。。。。
dalao介绍了埃式筛法。就是筛去所有质数的倍数。我做了一个变式:筛去质数的倍数,留下质数的次幂,最后没被筛去的就是答案数量,累加即可。

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int ip[100001]; 
long long t;
int main()
{
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	int n;
	cin>>n;
	for(int i=2;i<=n;i++)
	{
		ip[i]=1;
	}
    for(long long i=2;i<=n;i++)
    {
    	if(ip[i]==1)
    	{
    		for(int j=2*i;j<=n;j+=i)
    		{
    			ip[j]=0;
			}
			for(long long k=i*i;k<=n;k*=i)
			{
				ip[k]=2;
			}
		}
	}
//	for(int i=1;i<=n;i++)
//	{
//		cout<<ip[i]<<' ';
//	}
	for(int i=2;i<=n;i++)
	{
		if(ip[i]==1||ip[i]==2) t++;
	}
	cout<<t;
	fclose(stdin);
	fclose(stdout);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值