GCD Again
题目链接
题目大意
给定一个n,现在要求m的个数,满足gcd(n,m)>1 且(m<n)
题解
这一题很明显可以用欧拉函数,还可以用容斥原理,鉴于好久没写过容斥原理了,又把容斥原理写了一遍…
代码
欧拉函数
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n;
int eular(int x)
{
int t=x,ans=x;
for (int i=2;i<=sqrt(t);i++) if (t%i==0)
{
ans=(ans/i)*(i-1);
while(t%i==0) t/=i;
}
if (t>1) ans=(ans/t)*(t-1);
return ans;
}
int main()
{
while(scanf("%d",&n),n!=0)
{
printf("%d\n",n-1-eular(n));
}
return 0;
}
容斥原理
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
int n;
vector<int> V;
int solve(int n)
{
int cnt=1,ans=0,t;
for (int i=1;i<(1<<V.size());i++)
{
cnt=1; t=0;
for (int j=0;j<V.size();j++) if (i&(1<<j))
{
cnt*=V[j];
t++;
}
cnt=(n-1)/cnt;
if (t%2) ans+=cnt;
else ans-=cnt;
}
return ans;
}
int main()
{
while(scanf("%d",&n),n!=0)
{
V.clear();
int t=n;
for (int i=2;i<=sqrt(n);i++) if (n%i==0)
{
V.push_back(i);
while (n%i==0) n/=i;
}
if (n>1) V.push_back(n);
printf("%d\n",solve(t));
}
return 0;
}