题意:就是求出分数a/b ,其中数1<= a < b <= n并且gcd (a,b) = 1这样的分数有多少个。
殴拉函数:就是求小于n的所有整数a,并且gcd (a,n) = 1(1<= a < n)的个数。
它有一个公式及一些定理:
如果n是素数,那么殴拉函数f(n) = n-1.
f (n^k) =n^k-n^(k-1)
如果,gcd (n,m)= 1 ,那么f (n*m) = f (n)*f(m) (积性函数)
如果:p1,p2...pr是整除m的不同素数(由算术基本定理),则f(m)= m*(1-1/p1)(1-1/p2)...(1-1/pr);
速求出欧拉函数的值(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);
方法一,利用:殴拉函数的定理:如果:p1,p2...pr是整除m的不同素数(由算术基本定理),则f(m)= m*(1-1/p1)(1-1/p2)...(1-1/pr); 来解。
代码如下:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
const int N = 1000001;
bool prime[N+10];
int phi[N+10];
void init (){
int i;
for (i = 0; i < N; i++){
phi[i] = i;
prime[i] = true;
}
prime[1] = prime[0] = false;
for ( i = 2; i * i< N; i++){
if (prime[i]){
for (int j = i * i; j < N; j += i )
prime[j] = false;
}
}
for ( i = 2; i < N; i++){
if (prime [i]){
for (int j = i; j < N; j+=i )
phi[j] = phi[j] /i*(i-1); //f(m)= m*(1-1/p1)(1-1/p2)...(1-1/pr);
}
}
}
int main (){
init ();
int n;
__int64 sum;
while (scanf ("%d",&n) > 0 && n){
sum = 0;
for (int i = 2; i <= n; i++)
sum += phi[i];
cout<< sum <<endl;
}
return 0;
}
方法二:利用(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)
代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 1000002;
bool prime[N+10];
int phi[N+10];
__int64 E[N+10];
void init (){
int k = 1;
memset (prime,true, sizeof (prime));
prime[0] = prime[1] = false;
for (int i = 2; i < N; i++){
if (prime[i]){
phi[k++] = i;
E[i] = i-1;
}
for (int j = 1; j < k && phi[j] * i < N; j++ ){
prime[i*phi[j]] = false;
if (i % phi[j] == 0 ){
E[i*phi[j]] = E[i] * phi[j]; //若(N%a==0 && (N/a)%a==0) 则有:E(N)=E(N/a)*a;
break;
}
else
E[i*phi[j]] = E[i] *(phi[j] - 1); //若(N%a==0 && (N/a)%a!=0) 则有:E(N)=E(N/a)*(a-1)
}
}
}
int main (){
init ();
int n;
while (scanf ("%d",&n) > 0 && n){
__int64 sum = 0;
for (int i = 2; i <= n; i++)
sum += E[i];
cout << sum << endl;
}
}
殴拉函数:就是求小于n的所有整数a,并且gcd (a,n) = 1(1<= a < n)的个数。
它有一个公式及一些定理:
如果n是素数,那么殴拉函数f(n) = n-1.
f (n^k) =n^k-n^(k-1)
如果,gcd (n,m)= 1 ,那么f (n*m) = f (n)*f(m) (积性函数)
如果:p1,p2...pr是整除m的不同素数(由算术基本定理),则f(m)= m*(1-1/p1)(1-1/p2)...(1-1/pr);
速求出欧拉函数的值(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);
方法一,利用:殴拉函数的定理:如果:p1,p2...pr是整除m的不同素数(由算术基本定理),则f(m)= m*(1-1/p1)(1-1/p2)...(1-1/pr); 来解。
代码如下:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
const int N = 1000001;
bool prime[N+10];
int phi[N+10];
void init (){
int i;
for (i = 0; i < N; i++){
phi[i] = i;
prime[i] = true;
}
prime[1] = prime[0] = false;
for ( i = 2; i * i< N; i++){
if (prime[i]){
for (int j = i * i; j < N; j += i )
prime[j] = false;
}
}
for ( i = 2; i < N; i++){
if (prime [i]){
for (int j = i; j < N; j+=i )
phi[j] = phi[j] /i*(i-1); //f(m)= m*(1-1/p1)(1-1/p2)...(1-1/pr);
}
}
}
int main (){
init ();
int n;
__int64 sum;
while (scanf ("%d",&n) > 0 && n){
sum = 0;
for (int i = 2; i <= n; i++)
sum += phi[i];
cout<< sum <<endl;
}
return 0;
}
方法二:利用(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)
代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 1000002;
bool prime[N+10];
int phi[N+10];
__int64 E[N+10];
void init (){
int k = 1;
memset (prime,true, sizeof (prime));
prime[0] = prime[1] = false;
for (int i = 2; i < N; i++){
if (prime[i]){
phi[k++] = i;
E[i] = i-1;
}
for (int j = 1; j < k && phi[j] * i < N; j++ ){
prime[i*phi[j]] = false;
if (i % phi[j] == 0 ){
E[i*phi[j]] = E[i] * phi[j]; //若(N%a==0 && (N/a)%a==0) 则有:E(N)=E(N/a)*a;
break;
}
else
E[i*phi[j]] = E[i] *(phi[j] - 1); //若(N%a==0 && (N/a)%a!=0) 则有:E(N)=E(N/a)*(a-1)
}
}
}
int main (){
init ();
int n;
while (scanf ("%d",&n) > 0 && n){
__int64 sum = 0;
for (int i = 2; i <= n; i++)
sum += E[i];
cout << sum << endl;
}
}