找新朋友
Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4574Accepted Submission(s): 2314
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
hdu 1286 找新朋友 欧拉函数法及筛选法
/*分解成质因数 各个质因数的倍数<n的数的个数即使答案
1打印素数表
2 看素数表中能被n整除的prime[i]有哪些 标记下 这些prime[i]的倍数依然和n有公约数prime[i] 也都标记
3找出新朋友 即没有标记的
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
int i,j,cnt,prime[5000],mid,m,n,vis[32770],t,ans,use[5000],num;
memset(vis,0,sizeof(vis));
n=32768;
m=(int)sqrt(n+0.5);
cnt=0;
for(i=2;i<=m;i++) if(!vis[i])
{
for(j=i*i;j<n;j+=i) vis[j]=1;
}
for(j=2;j<n;j++) if(!vis[j]) prime[cnt++]=j;//打印素数表
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(vis,-1,(n+3)*sizeof(vis[0]));
i=0;num=0;ans=0;
while(prime[i]<=n)
{
if(n%prime[i]==0) use[num++]=prime[i];
i++;
}
for(i=0;i<num;i++)
{
mid=use[i];
while(mid<=n)
{
vis[mid]=0;
mid=mid+use[i];
}
}
for(i=0;i<=n;i++) if(vis[i]==0) ans++;
printf("%d\n",n-ans);
}
}
/
/
#include<stdio.h>//打表 节省时间 当数据很大 可以作模板的哦
#include<math.h>
#define maxn 32768
int phi[40000];
void get_PHI()
{
int i,j;
for (i = 1; i <= maxn; i++) phi[i] = i;
for (i = 2; i <= maxn; i += 2) phi[i] /= 2;
for (i = 3; i <= maxn; i += 2) if(phi[i] == i)
{
for (j = i; j <= maxn; j += i)
phi[j] = phi[j] / i * (i - 1);
}
}
int main()
{
int n;
get_PHI();
scanf("%d",&n);
while(n--)
{
int a;
scanf("%d",&a);
printf("%d\n",phi[a]);
}
return 0;
}
///
//非打表 节省空间 也可以做模板
#include<stdio.h>
#include<math.h>
int euler(int x)// 就是公式
{
int i, res=x;
for (i = 2; i <(int)sqrt(x * 1.0) + 1; i++)
if(x%i==0)
{
res = res / i * (i - 1);
while (x % i == 0) x /= i; // 保证i一定是素数
}
if (x > 1) res = res / x * (x - 1);//这里小心别溢出了
return res;
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int a;
scanf("%d",&a);
printf("%d\n",euler(a));
}
return 0;
}