题目
这里我们定义 φ(n)表示所有小于等于 n 与 n 互质数的个数。
例如 φ(10)=4,因为我们可以在 1∼10 中找到 1,3,7,9与 10 互质。
输入格式
第一行输入一个整数 t,表示测试数据组数。
接下来 t 行,每行有一个整数 n。
输出格式
对于每组测试数据输出 φ(n)。
数据范围
1≤t≤106, 1≤n≤106。
输出时每行末尾的多余空格,不影响答案正确性
样例输入
3
2
10
100
样例输出
1
4
40
思路
1.欧拉函数的模板题,由于多组数据,所以要用到筛法快速求,这里使用欧拉筛
2.先将106以内数筛出来,然后直接输出
3.数据输入量大,所以c++输入会超时,要用c输入
可参考我的博客素数筛与欧拉函数入门
代码
#include <bits/stdc++.h>
#include<stdio.h>
using namespace std;
const int maxx=1e6+7,inf=0x3f3f3f3f;
typedef long long ll;
ll phi[1000010],vis[1000010],prime[1000010];
int euler(int n)
{
int cnt=0;
phi[1]=1;//1要特判
for (int i=2; i<=n; i++)
{
if (vis[i]==0)//这代表i是质数
{
prime[cnt++]=i; phi[i]=i-1; //性质1
}
for (int j=0; j<cnt&&prime[j]*i<=n; j++)
{
vis[i*prime[j]]=1;
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];//性质4
break;
}
else phi[i*prime[j]]=phi[i]*phi[prime[j]];//性质3
}
} return cnt;
}
int main()
{
int t,a;
scanf("%d",&t);
euler(1000005);
while(t--)
{
scanf("%d",&a);
printf("%lld\n",phi[a]);
}
}