找新朋友(欧拉函数)

新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员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
个人心得:找互质数,朴素算法会超时,在了解了容斥原理后,根据那个公式sum=n*(p1-1)(p2-1)...(pi-1)/p1*p2*p3...pi;
p1到pi为n的素数因子。没学离散,容斥只是简单了解了下。看了还好,推导起来真的是一个头大!果断送人头出去,不玩了...绝望
附上代码吧
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<utility>
 6 #include<queue>
 7 #include<set>
 8 using namespace std;
 9 #define k 100003
10 int n;
11 long long sum;
12 int x[10000];
13 int flag;
14 bool prime(int x)
15 {
16     if(x<2) return false;
17     for(int i=2;i<=sqrt(x);i++)
18         if(x%i==0) return false;
19     return true;
20 
21 
22 }
23 void getsum()
24 {
25     flag=1;
26     long long t1=1,t2=1;
27     for(int i=2;i<n;i++)
28         if(n%i==0&&prime(i)) x[flag++]=i;
29         if(flag==1) {sum=n-1;return;}
30     for(int i=1;i<flag;i++)
31     {
32         t1*=(x[i]-1);
33         t2*=x[i];
34     }
35     sum=n*t1/t2;
36 
37 }
38 int main()
39 {
40    int t;
41    cin>>t;
42    while(t--)
43    {
44 
45        sum=0;
46        cin>>n;
47        if(n==1) {cout<<"1"<<endl;continue;}
48        getsum();
49        cout<<sum<<endl;
50 
51 
52 
53    }
54     return 0;
55 
56 
57 }

 

posted @ 2017-08-02 15:10  余生漫漫浪  阅读(249)  评论(0编辑  收藏  举报