问题及代码:
运行结果:
素数筛选。
断该会员的号码和N是否有大于1的公约数。
结果还没提交就看到某同学说超时了,我想是因为要一个个求公约数所以效率就慢了,果断考虑
换算法啊!
按题目所言,正整数N(1<n<32768),所以第一次筛选出32768里的所有素数;
再开一个新数组保存所有素数;然后筛选出旧朋友;最后“新朋友=总数-旧朋友-会长(会长是
第N号)”得到答案。
找新朋友
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 9 Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。
Input
第一行是测试数据的组数CN(Case number,1<CN<10000),接着有CN行正整数N(1<n<32768),表示会员人数。
Output
对于每一个N,输出一行新朋友的人数,这样共有CN行输出。
Sample Input
2 25608 24027
Sample Output
7680 16016
Author
Source
杭电ACM集训队训练赛(VII)
/*
*Copyright (c)2015,烟台大学计算机与控制工程学院
*All rights reserved.
*文件名称:HDU.cpp
*作 者:单昕昕
*完成日期:2015年2月8日
*版 本 号:v1.0
*/
#include<stdio.h>
#include<string.h>
int s[32769];
void Prime()
{
int i,j;
for(i=2; i<32769; i++)
for(j=i; j<32769; j+=i)
s[j]+=1;//为1时是素数
}
int main()
{
int prime[3600], j=0,cn,n,i,k;
memset(s,0,sizeof(s));//清零
Prime();
for(i=1; i<32769; i++)
if(s[i]==1)
prime[++j]=i;
scanf("%d",&cn);
while(cn--&&scanf("%d",&n)!=EOF)
{
int sum=0;
memset(s,0,sizeof(s));
for(i=1; prime[i]<=n/2; i++)
if(n % prime[i] == 0)
{
for(k=prime[i]; k<n; k+=prime[i])
if(s[k]==0)
{
sum++;
s[k]++;
}
}
printf("%d\n",n-sum-1);
}
return 0;
}
运行结果:
素数筛选。
学习心得:
一开始看到这题很自然的就想到先用数组编号,再写一个最大公约数的函数,然后一个个比较判断该会员的号码和N是否有大于1的公约数。
结果还没提交就看到某同学说超时了,我想是因为要一个个求公约数所以效率就慢了,果断考虑
换算法啊!
按题目所言,正整数N(1<n<32768),所以第一次筛选出32768里的所有素数;
再开一个新数组保存所有素数;然后筛选出旧朋友;最后“新朋友=总数-旧朋友-会长(会长是
第N号)”得到答案。