唯一分解定理:
给你一个数a,它只能被唯一分解成它的素因子乘积的形式,即N=p1^a1*p2^a2...pm^am,这里p1..pm是a的互异的素因子,从小到大,而ai则是a的分解式中pi的个数,比如18=2^1*3^2,36=2^2*3^2;
设根据惟一分解定理,将a化成素因子乘积的形式之后,在a以内与之互素的整数的个数为φ(a):
φ(a)就是所谓的欧拉函数。我们将n代入括号内:
int s=a for(i=1;i<=n;i++)
s=s*(1-1/p[i]); 循环结束后,s即为最终的结果:与a互质的数的个数。 如何理解这一定理:
题目要求的是与a互质的数的个数,即这些数中都不包括a的素因子,因此,反过来想,如果我们将[1,N]内的所有N的素因子的倍数都删除掉之后,那么余下的数不就是我们要求的数了吗?以下是这一想法的具体实现过程:为便于大家理解,我将n具体化,设n=12;则通过筛选法求出它的两个素因子2,3,[1,12]内2的倍数为2,4,6,8,10,12,将2的倍数全部删除,然后再在余下的6个数中删除3的倍数6和3,素因子已用完,剩下4个数即为最后结果,用定理M=12*(1-1/2)*(1-1/3)不谋而合。
import java.util.*;
public class Main {
static StringBuffer res = new StringBuffer();
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int a[]=new int[100000];//存放N的素数因子
int N;
while(in.hasNext()){
Arrays.fill(a,0);
N=in.nextInt();
if(N==0) break;
int j=0;
int k=N;
for(int i=2;i<=Math.sqrt(k);i++){//求出所有素因子
if(N%i==0){
while(N%i==0) N/=i;
a[j++]=i;
}
}
if(N!=1) a[j++]=N;
for(int i=0;i< j;i++){
k=k-k/a[i];
}
System.out.printf("%d\n",k);
}
}
}
import math
#是否为素数
def isPrime(n):
if n <= 1:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
def check(NUM):
K = NUM
if isPrime(NUM) is True:
return NUM-1
Alist=[]
for i in xrange(2,int(NUM**0.5)+1):
if NUM%i==0:
while NUM%i == 0:
NUM = NUM/i
Alist.append(i)
if NUM!=1:
Alist.append(NUM)
Alist=list(set(Alist))
for j in range(len(Alist)):
K = K-K/Alist[j]
return K