【数论】欧拉筛-素数

 参考某位大佬的博客,链接在下面,我个人认为他解释的挺清楚的。

欧拉筛法

  • 欧拉筛法的基本思想 :在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。
  • 代码 :
#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=1n​f(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

题目来源

ACM-ICPC 2018 南京赛区网络预赛                      


题意: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;
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值