直接法:是用(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),由此看来这点与直接法用的是同一公式,
其它数字也如此;
故此算法是先将所有的统统算出,无论用到用不到的都会算出,但在数字大的情况下运算速度还是很快的;