`
杭电1286——欧拉函数——找新朋友
新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。
Input
第一行是测试数据的组数CN(Case number,1<CN<10000),接着有CN行正整数N(1<n<32768),表示会员人数。
Output
对于每一个N,输出一行新朋友的人数,这样共有CN行输出。
Sample Input
2
25608
24027
Sample Output
7680
16016
补充欧拉函数:
在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目.如:φ(1)=1 此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。
互质:
互质是公约数只有1的两个整数,叫做互质整数。
看到这有没有发现 题目的意思就是让我们求 1——n-1 中与 n 互质的数的总数,自然就转化为求 φ(n)的值。
欧拉函数的C语言代码:
以两个等式为基础编写的代码
N = P1 ^ q1 * P2 ^ q2 * … * Pn ^ qn.
φ(N) = N * (1-1/P1) * (1-1/P2) * … * (1-1/Pn)
只和底数有关,和指数无关
10 = 1 × 2 × 5
ψ(10)=10×(1-1/2)×(1-1/5)=4;
30 = 1 × 2 × 3 × 5
ψ(30)=30×(1-1/2)×(1-1/3)×(1-1/5)=8;
8 = 2^3
ψ(8)=8×(1-1/2 ) =4;
#include<stdio.h>
#include<stdlib.h>
int eular(int n)
{
int ans = n;
int i;
for (i=2;i<=sqrt(n);i++) //找第一个因数
{
if (n % i == 0) //如果为因数 i
{
ans = ans * (i - 1) / i;
while (n % i == 0) //去 因数 i 的指数,直到 i 不为 更新后 n 的因数
n = n / i;
}
}
if (n > 1) //最后一个因数(也是最大的因数) 可能不符合循环条件而跳出循环,这里将其捕获。
ans = ans * (n - 1) / n;
return ans;
}
int main ()
{
int n,s;
scanf("%d",&n);
s=eular(n);
printf("%d",s);
return 0;
}
``
解题代码一
欧拉函数
#include<stdio.h>
#include <iostream>
#include <algorithm>
#include<string.h>
#include<math.h>
int eular(int n)
{
int ans = n;
int i;
for (i=2;i<=sqrt(n);i++)
{
if (n % i == 0)
{
ans = ans * (i - 1) / i;
while (n % i == 0)
n = n / i;
}
}
if (n > 1)
ans = ans * (n - 1) / n;
return ans;
}
int main()
{
int n,CN;
scanf("%d",&CN);
while (CN--)
{
scanf("%d",&n);
printf("%d\n",eular(n));
}
return 0;
}
解题代码二:
用空间换时间
#include<stdio.h>
#include <iostream>
#include <algorithm>
#include<string.h>
#include<math.h>
int a[33000]; //定义一个很大的数组
using namespace std;
int main()
{
int n,CN;
scanf("%d",&CN);
while (CN--)
{
scanf("%d",&n);
memset(a,0,sizeof(a)); //数组初始化为 0
int i;
int sum = 0;
for (i=2;i<=n/2;i++) //循环求 n 的因数
{
int k = 1;
while (n % i == 0 && k * i <= n) //由于 i 为 n 的因数,所以 i 的 k 倍 为老朋友.循环求出所以符合条件的下标 并赋值 1 。(这是解题的核心,极大的减少了时间的消耗)
{
a[k*i] = 1; //老朋友为 1 ,新朋友 为 0
k++;
}
}
for (i=1;i<n;i++) //输出
{
if (a[i] == 0)
sum++;
}
printf("%d\n",sum);
}
return 0;
}