参考某位大佬的博客,链接在下面,我个人认为他解释的挺清楚的。
欧拉筛法
- 欧拉筛法的基本思想 :在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。
- 代码 :
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6;
bool is_prime[N];
int prime[N],cnt;
void Euler(int n){
memset(is_prime,false,sizeof(is_prime));
int tot=0;
for(int i=2;i<=n;i++){
if(is_prime[i]==false){
prime[tot++]=i;
}
for(int j=0;j<tot&&prime[j]*i<=n;j++){
is_prime[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
cnt=tot;
}
int main()
{
Euler(100);
for(int i=0;i<cnt;i++){
printf("%d : %d\n",i+1,prime[i]);
}
return 0;
}
分析:
对于 i%prime[j] == 0 就break的解释 :
当 i是prime[j]的倍数时,i = k*prime[j],
如果继续运算 j+1,i*prime[j+1] = prime[j]*k*prime[j+1],
这里prime[j]是最小的素因子,当i = k*prime[j+1]时会重复,所以才跳出循环。
举个例子 :
i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,
prime[j+1] = 3,8*3 = 2*4*3 = 2*12,
在i = 12时会计算。因为欧拉筛法的原理便是通过最小素因子来消除。
A square-free integer is an integer which is indivisible by any square number except 11. For example, 6 = 2 ⋅3 6=2⋅3 is square-free, but 12 = 2^2⋅3 is not, because 2^2 is a square number. Some integers could be decomposed into product of two square-free integers, there may be more than one decomposition ways. For example, 6 = 1⋅6=6⋅ 1=2⋅ 3=3⋅ 2, n=ab ; are considered different if a!= b. f(n) is the number of decomposition ways that n=abn=ab such that aa and bb are square-free integers. The problem is calculating f(i) ∑i= 1-n f(i).
Input
The first line contains an integer T(T≤20), denoting the number of test cases.
For each test case, there first line has a integer n(n≤2⋅107).
Output
For each test case, print the answer ∑i=1nf(i).
Hint
f(i)=f(1)+....+f(8) ∑i=f(i)=f(1)+⋯+f(8)
=1+2+2+1+2+4+2+0=14=1+2+2+1+2+4+2+0=14.
样例输入
2 5 8
样例输出
8 14
题目来源
题意:f[i]表示i可以分解成为两个不能被平方数整除的数的个数(顺序不同算不同),对f[i]求前缀和。
思路:对于n,可以表示为n = a1^p1*a2^p2*...*an^pn,如果有一个pi>2,那么f[n] = 0,否则f[n] = 2^(sum(pi==1))。可以线性筛筛出来。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e7+10;
bool vis[N];
int prime[N];
ll ans[N],cnt;
void Euler(ll n){
vis[1]=true;
int tot=0;
memset(vis,false,sizeof(vis));
ans[1]=1;
for(ll i=2;i<=n;i++){
if(vis[i]==false){
prime[tot++]=i;
ans[i]=2;
}
for(ll j=0;j<tot;j++){
ll tmp=i*prime[j];
if(tmp>n) break;
vis[tmp]=true;
ll tt=prime[j]*prime[j];
if(i%prime[j]!=0){
ans[tmp]=ans[i]*ans[prime[j]];
}
else if(i%tt==0){
ans[tmp]=0;
//break;
}else{
ans[tmp]=ans[tmp/tt];
break;
}
}
}
cnt=tot;
}
int main()
{
Euler(N);
for(ll i=2;i<N;i++){
ans[i]=ans[i]+ans[i-1];
}
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
printf("%lld\n",ans[n]);
}
return 0;
}