欧拉筛模板:
const int maxn=1e7+10;
int cnt=0,prime[maxn];
bool isvisited[maxn];
void solve(int n){//筛 1-n 的数
for(int i = 2; i < n; i ++) {
if(!isvisited[i])
prime[cnt ++] = i;
for(int j = 0; j < cnt; j ++) {
if(i * prime[j] > n) break;
isvisited[i * prime[j]] = true;//每个合数都被他的最小质因数标记
if(i % prime[j] == 0) break; //当发现某个合数存在更小的质因数时就停止标记
}
}
}
有关例题: https://nanti.jisuanke.com/t/A1956
本题并未运用欧拉筛,而只是借用了欧拉筛的思想
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e7+5;
int prim[maxn],tot=0;
int vis[maxn],miu[maxn];
int ans[maxn];
void solve(){
ans[1]=1;//1对答案的贡献只有1
for(int i=2;i<maxn;i++){
if(vis[i]==0) prim[tot++]=i,ans[i]=2;//质数对答案的贡献为2
for(int j=0;j<tot;j++){
int k=prim[j]*i;
if(k>=maxn) break;
vis[k]=1;//上述均为欧拉筛的思想,不再解释
if(i%prim[j]) ans[k]=ans[i]*ans[prim[j]];//如果i不含有该质因子,无论i怎么分解,乘以该质因子之后都不会出现平方数,直接dp即可
else{//如果i含有该质因子
int tp=prim[j]*prim[j];
if(i%tp==0) ans[k]=0;//如果仅含有一个质因子还有救,两个质因子分开放就行了。
//否则就凉凉了,无论怎么放,a和b总会有一个含有平方因子
else ans[k]=ans[k/tp];// 该质因子被固定,i中也要拿出该质因子固定,则只有i/质因子自由
break;
}
}
}
}
int main(){
solve();
for(int i=1;i<maxn;i++){
ans[i]+=ans[i-1];
}
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%d\n",ans[n]);
}
return 0;
}