实验题目:素性检测
实验原理:
这里介绍了大素数的一些产生方法,包括:
1、Miller-Rabin素性检测;
2、Solovay-Stassen素性检测;
3、Fermat素性检测;等等
实验任务:
1、求100至200之间的素数。
代码如下:
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
bool isprime(int n){
for(int i=2;i<=sqrt(n);i++){
if(n%i==0){
return false;
}
}
return true;
}
int main(){
cout<<"100-200之间的素数如下"<<endl;
for(int i=100;i<=200;i++){
if(isprime(i)){
cout<<i<<endl;
}
}
}
2、利用Miller Babin素数筛法求出一个不小于1000的素数。
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#define random(a,b) (rand()%(b-a+1)+a) //[a,b]直接的随机数
typedef long long int ll;
//计算 rx*ry mod m
ll mod_mul(ll rx, ll ry, ll mod){
return (rx*ry)%mod;
}
// b^t mod m
ll mod_pow(ll b, ll t,ll mod){
//据太大 这样来处理
ll number=1;
ll num=b;
for(ll j=0;j<t;j++){
number=(number*num)%mod;
}
return number;
}
ll k;
ll s;
ll t;
bool Miller_Babin(ll n){
//求s,t
ll m=n-1;
s=0;
while(!(m&1)){
s++;
m>>=1;
}
t=m;
//cout<<"s,t的值"<<endl;
//cout<<s<<" "<<t<<endl;
for(int i=1;i<=k;i++){//循环安全参数k次
ll b=random(2,n-2);
ll r0=mod_pow(b,t,n);
if(r0==1|| r0==n-1){
continue;
}
int flag=1;
for(int j=1;j<=s-1;j++){
ll r1=mod_mul(r0,r0,n);
if(r1==n-1){
flag=0;
break;
}else{
r0=r1;
}
}
if(flag==1){
return false;
}
}
return true;
}
int main(){
srand((unsigned)time(NULL));
cout<<"请输入安全参数"<<endl;
cin>>k;
for(ll i=1001;;i++){
if(i%2==0){//保证输入为奇整数
continue;
}
if(Miller_Babin(i)){
cout<<"s,t的值"<<endl;
cout<<s<<" "<<t<<endl;
cout<<endl;
cout<<i<<endl;
return 0;
}
}
}
3、求如下整数对的最大公因数
(55,85) (202,282)
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
/*
举例:求8251与6105的最大公约数,
8251=6105x1+2164
6105=2146x2+1813,
2164=1813x1+333,
1813=333x5+148,
333=148x2+37,
148=37x4,∴37是148和37的最大公约数,也就是8251和6105的最大公约数。
*/
//辗转相除法求最大公因数
int Max_Gcd(int a,int b){
if(a<b){
swap(a,b);
}
int Z=0,Mod=-1;
int flag=1;
int result=0;
while(Mod!=0){//余数不为0则 接着循环
Z=a/b;
Mod=a%b;
if(flag==1 && Mod==0){
result=b;
flag=0;
break;
}
if(Mod!=0){
result=Mod;
}
a=b;
b=Mod;
}
return result;
}
int main(){
int k;
cout<<"输入你测试数据的个数"<<endl;
cin>>k;
while(k--){
cout<<"输入数据a和数据b,中间以空格隔开"<<endl;
int a,b;
cin>>a>>b;
cout<<Max_Gcd(a,b)<<endl;
}
}
4、运用广义欧几里得除法求整数s,t,使得sa+tb=(a,b)
(1)1613,3589 (2)2947,3772
分析思路:
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
/*
3589= 2*1613+363,
1613= 4*363+161,
363= 2*161+41,
161=3*41+38,
41=1*38+3,
38=12*3+2,
3=1*2+1,
2=2*1
1=3-2*1
=3-(38-12*3)*1
=-38+(41-1*38)*13
=41*13-(161-3*41)*14
=-14*161+(363-2*161)*55
=363*55-(1613-4*363)*124
=-1613*124+(3589-2*1613)*551
=551*3589-1226*1613
即s=551,t=-1226.
改变书写格式总结规律:
3+(-1)*2=1;
38+(-12)*3=2;
41+(-1)*38 =3;
161+(-3)*41=38;
363+(-2)*161=41;
1613+(-4)*363=161;
3589 +(-2)*1613=363;
*/
//辗转相除法求最大公因数
vector<int> q;
int result;//记录最大公约数
int Max_Gcd(int a,int b){
int count=0;
if(a<b){
swap(a,b);
}
int Z=0,Mod=-1;
while(Mod!=0){//余数不为0则 接着循环
Z=a/b;
Mod=a%b;
q.push_back(Z);//记录q值
count++;//记录运算步骤
if(Mod!=0){
result=Mod;
}
a=b;
b=Mod;
}
return count;
}
int main(){
int k;
cout<<"输入你测试数据的个数"<<endl;
cin>>k;
while(k--){
cout<<"输入数据a和数据b,中间以空格隔开"<<endl;
int a,b;
cin>>a>>b;
int count=Max_Gcd(a,b);
cout<<"最大公约数为:"<<endl;
cout<<result<<endl;
vector<int> q_;
for(int i=q.size()-2;i>=0;i--){
q_.push_back(-q[i]);
}
cout<<"调整好之后的q的值如下:"<<endl;
for(int i=0;i<q_.size();i++){
cout<<q_[i]<<" ";
}
cout<<endl;
cout<<"循环次数如下"<<endl;
cout<<count-2;
cout<<endl;
//倒推求解规律如下
int a1[1005];
int b1[1005];
a1[0]=1;
b1[0]=q_[0];
for(int i=1;i<=count-2;i++){
a1[i]=b1[i-1];
b1[i]=b1[i-1]*q_[i]+a1[i-1];
}
cout<<"结果为"<<endl;
if(a>b){
cout<<a1[count-2]<<" "<<b1[count-2];
}else{
cout<<b1[count-2]<<" "<<a1[count-2];
}
q.clear();
cout<<endl;
}
}