1.埃式筛法
应用:对很多整数进行素性测试-->要枚举n以内的素数
思路:2--n范围内的所有整数,依次遍历。遍历过程中如果该数是素数则将其的倍数都划去(可以想象他的倍数一定为非素数)。遍历完成后。就可以枚举n以内的素数了。
模板:
void sieve(int n)
{
int t = 0;
for(int i = 0;i<=n;i++)
{
is_prime[i] = true;//先将初始值均赋为true
}
for(int i = 2;i<=n;i++)//依次遍历
{
if(is_prime[i])//检验到目前为止其是不是素数
{
t++;//是的 素数数目加一
for(int j = 2*i;j<=n;j+=i)
{
is_prime[j] = false;//其整数倍不是素数,置为false
}
}
}
printf("%d\n",t);//素数的数量
}
#include<stdio.h>
#include<iostream>
using namespace std;
bool is_prime[1000100];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int t = 0;
for(int i = 0;i<=n;i++)
{
is_prime[i] = true;
}
for(int i = 2;i<=n;i++)
{
if(is_prime[i])
{
t++;
for(int j = 2*i;j<=n;j+=i)
{
is_prime[j] = false;
}
}
}
printf("%d\n",t);
}
return 0;
}
变换题+bfsPrime Path POJ - 3126
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn = 10010;
bool book[maxn],prime[maxn];
int cnt[maxn],t[4],a,b,temp;
void is_prime2()//判断是否是负数
{
int flag = 0;
for(int i = 1000;i<=maxn;i++)
{
flag = 0;
for(int j = 2;j*j<=i;j++)
{
if(i%j == 0)
{
flag = 1;
prime[i] = false;
}
}
if(!flag)
prime[i] = true;
}
}
int bfs(){
bool dis[maxn];
queue <int>q;
int v,i,j,temp,vtemp,count[maxn],t[4];
memset(dis,false,sizeof(dis));
memset(count,0,sizeof(count));
q.push(a);
dis[a]=true;
while(!q.empty()){
v=q.front();
q.pop();
t[0]=v/1000;
t[1]=v%1000/100;
t[2]=v%100/10;
t[3]=v%10;
for(j=0;j<4;j++){
temp=t[j];
for(i=0;i<10;i++)
if(i!=temp){
t[j]=i;
vtemp=t[0]*1000+t[1]*100+t[2]*10+t[3];
if(!dis[vtemp] && prime[vtemp]){
count[vtemp]=count[v]+1;
dis[vtemp]=true;
q.push(vtemp);
}
if(vtemp==b) return count[vtemp];
}
t[j]=temp;
}
if(v==b) return count[v];
}
return -1;
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%d%d",&a,&b);
is_prime2();
int key = bfs();
if(key == -1)
{
cout<<"Impossible"<<endl;
}
else
cout<<key<<endl;
}
return 0;
}
2.快速幂运算
反复平方法
n为奇数:
偶数:
模板:小白书例题UVA10006 Carmichael Numbers
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
bool is_prime[70000];
void prime()
{
for(int i = 2;i*i<70000;i++)
{
if(is_prime[i])
{
for(int j = 2*i;j<70000;j+=i)
{
is_prime[j] = false;
}
}
}
}
long long mod_pow(long long x,long long n,long long mod)
{
long long res = 1;
while(n>0)
{
if(n&1) //相当于n%2,1.起初奇数再乘以一个x 2.或者最后时res*x
{
res = res*x%mod;
}
x = x*x%mod; //不断进行反复平方
n>>=1;//相当于n/=2;
}
return res;
}
int main()
{
int flag;
long long n;
memset(is_prime,true,sizeof(is_prime));
prime();
while(scanf("%lld",&n)!=EOF&&n)
{
flag = 0;
if(is_prime[n])
{
printf("%lld is normal.\n",n);
continue;
}
for(int i = 2;i<n;i++)
{
long long c = mod_pow(i,n,n);
if(c!=i%n)
{
flag = 1;
break;
}
}
if(!flag)
{
printf("The number %lld is a Carmichael number.\n",n);
}
else
{
printf("%lld is normal.\n",n);
}
}
return 0;
}