这个要是直接用找有公约数的会超时的。要用筛选法,就是在2到x/2中找到能被x整除的数,

然后将那个数标记用hash[i]=1(hash初始化为0);再将那个数的倍数(小与x)找到再将

他们标记(即都符合是有大于1 的公约数)最后找到标记为0的个数s(及新朋友),要减1

(因为刚才算的都没包括x,hash[x]=0的本身要除掉),网上的还用了欧拉公式(比较牛的)

筛选法代码:

View Code
 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 /*int gcd(int a,int b)
 5 {
 6     int r;
 7     while(b!=0)
 8     {
 9         r=a%b;
10         a=b;
11         b=r;
12     }
13     return a;
14 }*/
15 int hash[32770];
16 int main()
17 {
18     int i,j,cn,s,x;
19     cin>>cn;
20     while(cn--)
21     {
22         memset(hash,0,sizeof(hash));
23         s=0;
24         cin>>x;
25         for(i=2;i<=x/2;i++)
26         {
27             if(x%i==0)
28                for(j=i;j<x;j+=i)
29                   hash[j]=1;    
30         }
31         for(i=1;i<=x;i++)
32             if(hash[i]==0)
33                s++;
34         cout<<s-1<<endl;
35     }
36     return 0;
37 }

欧拉公式:

View Code
 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstdlib>
 4 #include <cstring>
 5 
 6 int eular(int n)
 7 {
 8         int ret=1,i;
 9         for (i=2;i*i<=n;i++)
10         {
11                 if (n%i==0)
12                 {
13                         n/=i,ret*=i-1;
14                         while (n%i==0)
15                                 n/=i,ret*=i;
16                 }
17         }
18         if (n>1)
19                 ret*=n-1;
20         return ret;
21 }
22 int main()
23 {
24         int n ,a ;
25         scanf("%d",&n);
26         while(n--)
27         {
28                 scanf("%d",&a);
29                 int res = eular(a);
30                 printf("%d\n",res);
31         }
32         return 0;
33 }

 

posted on 2012-08-16 10:24  xinmenghuairi  阅读(264)  评论(0编辑  收藏  举报