找新朋友
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员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
题意:求1~N-1中与N互质的数有几个
因为该题的N比较小,所以一些暴力的方式也是可以过的,比如说对于每个给定的N,可以求出它的质因数,然后跟它有相同约数的数便可以通通排除掉,这个方法相信大家都是会的,我就不多说什么了这次我主要要讲的是欧拉函数,若n的所有质因子有p1,p2,p3,…,pk,那么根据欧拉函数可得n以内与n互质的数的个数
至于该式子的证明,在此不做解释,有兴趣直接点链接
所以我们只需一边计算n的质因数,一边计算φ(n)即可,而1/pi,为了防止精度问题对其造成影响,我们可以把n乘进去,这样就成了n-n/pi,因为pi是n的质因子,所以n必定能被pi整除,这样就不会因为精度问题而造成结果错误了
好了,闲话不多说,上代码
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 1000000;
const int inf = 1000000000;
const int mod = 258280327;
int euler(int n)
{int ans=n;for(int i=2;i*i<=n;i++)if(n%i==0){ans=ans-ans/i;while(n%i==0)n/=i;}if(n>1)ans=ans-ans/n;return ans;
}
int main()
{int t,n;scanf("%d",&t);while(t--){scanf("%d",&n);printf("%d\n",euler(n));}return 0;
}
菜鸟成长记