题目描述
FF博士最近在研究MMT数。
如果对于一个数n,存在gcd(n,x)<>1并且n mod x<>0 那么x叫做n的MMT数,显然这样的数可以有无限个。
FF博士现在想知道在所有小于n的正整数里面有多少个n的MMT数。
输入格式
仅一行一个数为n。
输出格式
输出所有小于n的正整数里面有多少个n的MMT数。
样例数据
样例输入
10
样例输出
3
样例解释
3个数分别是 4 6 8,gcd(n,x)的意思是求n和x的最大公约数。
数据范围
对于50%的数据 n<=1000000
对于100%的数据n<=maxlongint
题目分析
gcd<>1即为不互质的数,补集即欧拉函数
n mod x<>1即不是约数
因此答案为n-φ(n)-约数(n)+1
为什么要加1?因为1又是n的约数也与n互质
源代码
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
int n,vst[50005],Prime[50005],cnt=0;
void Get_Prime() {
//筛选法求素数表
memset(vst,0,sizeof(vst));
vst[0]=vst[1]=1;
for(int i=2; i<=sqrt(50000); i++)
if(vst[i]==0)
for(int j=i*i; j<=50000; j+=i)vst[j]=1;
for(int i=2; i<=50000; i++)
if(vst[i]==0)Prime[++cnt]=i;
}
int Euler(int x) { //欧拉函数
int sum=x;
for(int i=2; i<=sqrt(x); i++) {
if(x%i==0) {
sum-=sum/i; //减掉i的倍数
while(x%i==0)x/=i;
}
}
if(x>1)sum-=sum/x; //没有除尽
return sum;
}
int tmp,sum=1;
int Solve(int p) { //约数个数
int cnt=0;
while(tmp%p==0) {
tmp/=p;
cnt++;
}
sum*=cnt+1;
}
int main() {
Get_Prime();
n=Get_Int();
int e=Euler(n);
tmp=n;
for(int i=1; i<=cnt; i++)
if(Prime[i]<=n)Solve(Prime[i]);
else break;
if(tmp>1)sum*=2;
printf("%d\n",n-e-sum+1);
return 0;
}