您的位置:首页 > 其它

51nod 1536 不一样的猜数游戏 (找规律+素数筛)

2017-11-12 16:19 441 查看
传送门51nod 1536

前置技能

素书筛法求区间内的素数。大体思路是,写出区间 1~n 内的所有数,然后从 2开始扫描,把 2 的倍数(不包括2)全部删除,然后寻找下一个未删除的数(为质数),再把它的倍数(不包括其本身)删除,最后剩下的就是区间内所有的质数。

思路

一拿到题,一 lemon逼。曾一度以为答案是 n-1 ……我们可以肯定,答案不超过 n ……然后自己猜测是否会是求 1~n 中质数的个数。于是我自己试着写了几组数据推测答案。

以 n = 6 为例, 1,2,3,4,5,6 中都是 1 的倍数,所以提问了也白提问。为 2 的倍数的有 2,4,6 ;为 3 的倍数的有 3,6;为 4 的倍数的有 4;为 5 的倍数的有 5;为 6 的倍数的只有 6,而 6 可以通过提问是否为 2,3的倍数得到。所以只需要提问 4 次。

我们发现提问的数中除了质数外还有一个 4。4只有一个质因子 2,所以只提问是否为 2 的倍数是不能确定的,必须提问 4本身。所以我就推测:答案应该是质因子数为 1 的数的个数。因为其他的数,都可以通过提问他的每个质因子来确定,而质数和质因子为 1 的数则必须提问本身。

代码

#include<stdio.h>
#include<string.h>

int tol,p[1010],pri[1010]; //p保存素数列表

void init()
{ //素书筛求区间内素数
int i,j;
tol=0;
memset(pri,1,sizeof(pri));
for(i=2;i<1010;i++) //枚举所有因子
if(pri[i])
{ //若未删除则该数为素数
p[tol++]=i;
for(j=2*i;j<1010;j+=i) pri[j]=0; //将其倍数删除
}
}

int main()
{
int i,j,n,x,num,ans;
init();
while(~scanf("%d",&n))
{
ans=0;
for(i=2;i<=n;i++)
{ //判断每个数质因子的个数
x=i;
num=0;
for(j=0;p[j]<=i;j++)
{
if(x%p[j]==0) num++;
while(x%p[j]==0) x/=p[j]; //将所有的该因子去除
}
if(x>1) num++;
if(num==1) ans++; //如果质因子数为 1则答案 +1
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: