H - Carmichael Numbers(素数筛&快速幂)

题意:给定,若不为素数
且对则该数为

思路:因为只有的大小,可以用素数筛预处理的所有数。

接下来用快速幂的板子暴力遍历判断即可。

时间复杂度:

这里复杂度可以用筛降到

AC代码:(线性筛)

#include<cstdio>
using namespace std;
const int N=65000;
int a[N+5],mod;
typedef long long ll;
void ss(int n){ //线性筛 
    a[0]=a[1]=1;
    for(int i=2;i*i<=n;i++)
        if(!a[i])
            for(int j=i*i;j<=n;j+=i) a[j]=1;
}
ll ksm(ll x,int n){//(快速幂板子) 这里x用ll因为 x*x可能会爆int  
    ll ans=1;
    while(n){
        if(n&1) ans=ans*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return ans;
}
int main(){
    int n;ss(N);
    while(~scanf("%d",&n)&&n){
        if(!a[n]){
            printf("%d is normal.\n",n);
            continue;
        }
        int f=0;mod=n;
        for(int i=2;i<n;i++)
        {
            if(ksm(i,n)!=i)
            {
                f=1;
                break;
            }
        }
        if(!f) printf("The number %d is a Carmichael number.\n",n);
        else printf("%d is normal.\n",n);
    }
    return 0;
}

AC代码:Euler筛

#include<cstdio>
using namespace std;
const int N=65000;
int a[N+5],mod,p[N];
typedef long long ll;
void ss(int n){
    for(int i=2,cnt=0;i<=n;i++)
    {
        if(!a[i]) p[cnt++]=i;
        for(int j=0;j<cnt&&p[j]*i<=n;j++)
        {
            a[i*p[j]]=1;//最小质因数筛合数。 
            if(i%p[j]==0) break;//如果i被筛过 则i*p[j+1]也被筛过了. 
        }
    } 
} 
ll ksm(ll x,int n){//(快速幂板子) 这里x用ll因为 x*x可能会爆int  
    ll ans=1;
    while(n){
        if(n&1) ans=ans*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return ans;
}
int main(){
    int n;ss(N);
    while(~scanf("%d",&n)&&n){
        if(!a[n]){
            printf("%d is normal.\n",n);
            continue;
        }
        int f=0;mod=n;
        for(int i=2;i<n;i++)
        {
            if(ksm(i,n)!=i)
            {
                f=1;
                break;
            }
        }
        if(!f) printf("The number %d is a Carmichael number.\n",n);
        else printf("%d is normal.\n",n);
    }
    return 0;
}