ACM--steps--2.1.7--欧拉函数

来源:互联网 发布:电脑阅卷软件 编辑:程序博客网 时间:2024/06/09 20:10

找新朋友

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2786 Accepted Submission(s): 1306 
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
22560824027
 
Sample Output
768016016
 
Author
SmallBeer(CML)
 
Source
杭电ACM集训队训练赛(VII)



欧拉函数的定义:E(k)=([1,n-1]中与n互质的整数个数).
   
     因为任意正整数都可以唯一表示成如下形式:
                     k=p1^a1*p2^a2*……*pi^ai;(即分解质因数形式)
    可以推出:E(k)=(p1-1)(p2-1)……(pi-1)*(p1^(a1-1))(p2^(a2-1))……(pi^(ai-1))
               =k*(p1-1)(p2-1)……(pi-1)/(p1*p2*……pi);------------->(1)
               =k*(1-1/p1)*(1-1/p2)....(1-1/pk)--------------------------->(2)
     ps:在程序中利用欧拉函数如下性质,可以快速求出欧拉函数的值(a为N的质因素)
若(N%a==0 && (N/a)%a==0) 则有:E(N)=E(N/a)*a;

若(N%a==0 && (N/a)%a!=0) 则有:E(N)=E(N/a)*(a-1);

在程序计算中,运用的是第一个通式。

程序判断中,循环判断只进行到了sqrt(a),
因数都是成对出现的。比如,100的因数有:1和100,2和50,4和25,5和20,10和10。看出来没有?成对的因数,其中一个必然小于等于100的开平方,另一个大于等于100的开平方。
当出现大于sqrt(a)的质因数时,循环已经进行到最后,将最后一个小于sqrt(a)的质因数取出后。


#include<iostream>#include<cmath>using namespace std;int Euler(int a){    int ans=a;    int i;//i表示a的质因子。    for(i=2;i<(int)sqrt(a)+1;i++)    {        if(a%i==0)        //欧拉函数的通式。        ans=ans*(i-1)/i;    //保证每次循环都是质因子。    //假设该数有因数2,4,4也可以分解2X2。    while(a%i==0)    {        a/=i;    }    }    //要考虑到最后剩下的那个因子,若是1则所有的质因数全部计算完,如没有,则应该加上最后那个质因数。    if(a>1)    {        ans=ans*(a-1)/a;    }    return ans;}int main(){    int T,n;    cin>>T;    while(T--)    {        cin>>n;        cout<<Euler(n)<<endl;    }    return 0;}<span style="color:#33ff33;"></span>



0 0