这个要是直接用找有公约数的会超时的。要用筛选法,就是在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 }