欧拉函数筛选算法

直接法:是用这里写图片描述(P是数N的质因数)
筛选法
首先看算法:

long long a[1000020];
    memset(a,0,sizeof(a));
    a[1]=1;
    for(int i=2; i<1000020; i++)
        if(!a[i])
            for(int j=i; j<1000020; j+=i) {
                if(!a[j])
                    a[j]=j;
                a[j]=a[j]/i*(i-1);
            }

我们将其放入主函数中,由于100020太大先用小数的来试验,比如先用30代替100020

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
ll n;
const ll MAXN = 30;
ll a[MAXN];
int main()
{
    while(scanf("%lld",&n) && n)
    {
    memset(a,0,sizeof(a));
    a[1] = 1;
    for(ll i=2; i<MAXN; i++){
        if(!a[i]){
            for(ll j=i; j<MAXN; j+=i){
                if(!a[j]){
                    a[j] = j;
                    cout <<"1.a["<<j<<"]="<<a[j]<<endl;//将此时的a[j]打印出来
                } 
                a[j] = a[j]/i*(i-1);
                cout <<"1.a["<<j<<"]="<<a[j]<<endl;//将此时的a[j]打印出来
            }
        }
        cout <<"================="<<endl;//使j与j之间更工整
    }
            printf("%d\n",a[n]);    
    }
    return 0;
}

先输入个4跑一遍
这里写图片描述这里写图片描述
发现第一组里 j 全部是2的倍数,第二组里全是3的倍数,第三组为 因为原本应该是4的倍数,但4的倍数也是2的倍数,故囊括在第2组中故为空,第四组为5的倍数。。。。。。
第一组:开始时a[2]==0,从代码中得知此时赋值为2,然后开始进行/i*(i-1) 得到a[2]=1,第一组全部如此。
第二组:有些数字由于是2的倍数,又再次出现比如6,由于此时a[6]不为空 所以仅/i*(i-1),由此看来这点与直接法用的是同一公式,这里写图片描述
其它数字也如此;
故此算法是先将所有的统统算出,无论用到用不到的都会算出,但在数字大的情况下运算速度还是很快的;

猜你喜欢

转载自blog.csdn.net/orange1710/article/details/81484322
今日推荐