题目大意:
给定一个正整数n(1 ≤ n ≤ 1,000,000,000),求小于它并且和它互质的数的数量(即欧拉函数)。
两数互质即两数的最大公约数只有1一个,即两者只能同时被1整除而不能被其它任何数同时整除。
现有多个测例,每个测例中都会给出一个正整数n,对于每个测例都要输出其欧拉函数的值。
注释代码:
//欧拉函数的计算公式为:
//eula(n) = n × ∏(1 - 1/pi)
//其中p为n的所有因子
//筛法就是将n的所有因子展开后一个个筛选
//其中因子从从小到大进行扫描筛选
//如果碰到一个因子(此时n必然能整除它)就筛选到
//在结果上乘以一个(1 - 1/pi),并将该因子除尽
//那剩余的数继续筛选其它因子
//比如n = 1260 = 2 × 2 × 3 × 5 × 7
//因子d从2开始扫描,发现1260可以整除2,将2筛选出,用ans × (1 - 1/2)
//ans初始化为n
//然后将所有2因子都除去,则还剩n = 105 = 3 × 5 × 7,然后用同样的方法得到因子3
//再在ans上乘以(1 - 1/3),知道最后将7也算进去为止
//为了减小扫描范围,每扫描出一个就将d的上限降低为√n,因为每筛选出一个p就要从n中除去因子p
//由于n减小,d的上限也必然的减小,上限用d * d <= n很合适
//求欧拉函数表的模板:
// void
// eular() {//求1 - N的欧拉函数值,直接打表
//
// int i, j;
//
// eu[1] = 0; //一般1的欧拉函数值由题意决定,这里默认为1
// for ( i = 2; i <= N; i++ )
// if ( !eu[i] )
// for ( j = i; j <= N; j += i ) {
//
// if ( !eu[j] )
// eu[j] = j;
//
// eu[j] -= eu[j] / i;
// }
// }
/*
* Problem ID : POJ 2407 Relatives
* Author : Lirx.t.Una
* Language : C
* Run Time : 0 ms
* Run Memory : 172 KB
*/
#include <stdio.h>
int
main() {
int n;//给定的正整数
int d;//divisor,因子(被除数),用筛法扫描时的筛选因子
int ans;
while ( scanf("%d", &n), n ) {
if ( 1 == n ) {//1的欧拉函数必然为0
puts("0");
continue;
}
for ( ans = n, d = 2; d * d <= n; d++ )
if ( !( n % d ) ) {//查看d是否是n的因子
ans -= ans / d;//欧拉函数的公式
do {
n /= d;//将因子d从n中除去
}
while ( !( n % d ) );
}
//特殊情况,比如n已经为5 × 7了,刚除去5,d刚好涨到6而n由于除去5而变成7
//此时6 * 6 > 7而退出上面的循环而漏掉了最后一个因子7
//此语句就是为了避免这种漏网之鱼
if ( n != 1 )
ans -= ans / n;
printf("%d\n", ans);
}
return 0;
}
无注释代码:
#include <stdio.h>
int
main() {
int n;
int d;
int ans;
while ( scanf("%d", &n), n ) {
if ( 1 == n ) {
puts("0");
continue;
}
for ( ans = n, d = 2; d * d <= n; d++ )
if ( !( n % d ) ) {
ans -= ans / d;
do {
n /= d;
}
while ( !( n % d ) );
}
if ( n != 1 )
ans -= ans / n;
printf("%d\n", ans);
}
return 0;
}
单词解释:
relative:adj, 相对的,相关的; n, 亲戚,相关物
prime:n, 素数(质数)
be prime to:和...互质