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;
} 
京公网安备 11010502036488号