晚上睡着,起来a一题 //有陷阱~~~
http://poj.org/problem?id=2407
此题考虑的是欧拉函数的应用
判断与其互质的个数:
注意 φ函数的值 通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数。φ(1)=1(唯一和1互质的数就是1本身)。 (注意:每种质因数只一个。比如12=2*2*3
那么φ(12)=12*(1-1/2)*(1-1/3)=4)
注意如果一个数是质数的话,那么他的质因数只有他自己本身:
post code:
#include<stdio.h> #include<math.h> int fun(int n); int sample,flag=0;; int main() { int num,max,i,c; while(scanf("%d",&num)&&num!=0) { if(num==1) {printf("0\n");continue;} if(num==2) {printf("1\n");continue; } sample=num; flag=0; max=(int)(sqrt((float)num)+1); for(i=2;i<=max;i++) { //key point if(num%i==0) {if(i<=(num/i)){c=fun(i);if(i!=(num/i))fun(num/i);}} //判断同时能够整除的两个数是否为质数 注意 前面那个数要小于后面那个数, 注意相等的情况只计算一遍 } if(flag==0)printf("%d\n",sample-1); //此数本身是质数,仅有一个质因数是自己本身 else printf("%d\n",sample); } } int fun(int n) //判断能整除的数是质数的话,进行欧拉函数的运算; { int m,i; m=(int )(sqrt((float)n)+1); if(n==2) {sample=sample-sample/n;flag=1;return 0;} for(i=2;i<=m;i++) { if(n%i==0)return 0; } sample=sample-sample/n; flag=1; return 0; }
关于欧拉函数的求解问题:
发现还有一种方法来判断是互素的个数:
欧拉函数公式的第二种求法:
已知一个数n
求f(n)
n=m1k1 +m2k2 + m3k3 + m4k4
f(n)=m1k1-1 *m2k2-1 * m3k3-1 *m4k4-1 *(k1-1)*(k2-1)*(k3-1)*(k4-1);
就求得了欧拉函数的取值:
post code: 约400B 注意其中间接用到了 筛选法求素数;
#include<stdio.h> int num; int fun() { int i,m,res=1; m=num; if(num==1){printf("0\n");return 0;} for(i=2;i<=m;i++) //这里利用到了素数的筛选法~~ 直接将合数的情况给筛出去了 这个i<=m是关键 { if(m%i==0) {res*=i-1;m/=i;} // 这里是求每个质因数的m-1 while(m%i==0){ res*=i; //这里是求每个质因数的mk-1 m/=i; } } if(m>1){res=num-1;printf("%d\n",res);} //如果是质数则 仅有一个质因数是器本身,要-1; else printf("%d\n",res); } int main() { while(scanf("%d",&num)&&num!=0) fun(); }