大數模擬 加減乘除 判斷大數是否為素數 板子
過載+ - * /
#include<iostream>
#include<vector>
#include<string>
using namespace std;
struct Wint:vector<int>//用標準庫vector做基類,完美解決位數問題,同時更易於實現
{
//將低精度轉高精度的初始化,可以自動被編譯器呼叫
//因此無需單獨寫高精度數和低精度數的運算函式,十分方便
Wint(int n=0)//預設初始化為0,但0的儲存形式為空
{
push_back(n);
check();
}
Wint& check()//在各類運算中經常用到的進位小函式,不妨內建
{
while(!empty()&&!back())pop_back();//去除最高位可能存在的0
if(empty())return *this;
for(int i=1; i<size(); ++i)
{
(*this)[i]+=(*this)[i-1]/10;
(*this)[i-1]%=10;
}
while(back()>=10)
{
push_back(back()/10);
(*this)[size()-2]%=10;
}
return *this;//為使用方便,將進位後的自身返回引用
}
};
//輸入輸出
istream& operator>>(istream &is,Wint &n)
{
string s;
is>>s;
n.clear();
for(int i=s.size()-1; i>=0; --i)n.push_back(s[i]-'0');
return is;
}
ostream& operator<<(ostream &os,const Wint &n)
{
if(n.empty())os<<0;
for(int i=n.size()-1; i>=0; --i)os<<n[i];
return os;
}
//比較,只需要寫兩個,其他的直接代入即可
//常量引用當引數,避免拷貝更高效
bool operator!=(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return 1;
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return 1;
return 0;
}
bool operator==(const Wint &a,const Wint &b)
{
return !(a!=b);
}
bool operator<(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return a.size()<b.size();
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return a[i]<b[i];
return 0;
}
bool operator>(const Wint &a,const Wint &b)
{
return b<a;
}
bool operator<=(const Wint &a,const Wint &b)
{
return !(a>b);
}
bool operator>=(const Wint &a,const Wint &b)
{
return !(a<b);
}
//加法,先實現+=,這樣更簡潔高效
Wint& operator+=(Wint &a,const Wint &b)
{
if(a.size()<b.size())a.resize(b.size());
for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,const Wint &b)
{
return a+=b;
}
//減法,返回差的絕對值,由於後面有交換,故引數不用引用
Wint& operator-=(Wint &a,Wint b)
{
if(a<b)swap(a,b);
for(int i=0; i!=b.size(); a[i]-=b[i],++i)
if(a[i]<b[i])//需要借位
{
int j=i+1;
while(!a[j])++j;
while(j>i)
{
--a[j];
a[--j]+=10;
}
}
return a.check();
}
Wint operator-(Wint a,const Wint &b)
{
return a-=b;
}
//乘法不能先實現*=,原因自己想
Wint operator*(const Wint &a,const Wint &b)
{
Wint n;
n.assign(a.size()+b.size()-1,0);
for(int i=0; i!=a.size(); ++i)
for(int j=0; j!=b.size(); ++j)
n[i+j]+=a[i]*b[j];
return n.check();
}
Wint& operator*=(Wint &a,const Wint &b)
{
return a=a*b;
}
//除法和取模先實現一個帶餘除法函式
Wint divmod(Wint &a,const Wint &b)
{
Wint ans;
for(int t=a.size()-b.size(); a>=b; --t)
{
Wint d;
d.assign(t+1,0);
d.back()=1;
Wint c=b*d;
while(a>=c)
{
a-=c;
ans+=d;
}
}
return ans;
}
Wint operator/(Wint a,const Wint &b)
{
return divmod(a,b);
}
Wint& operator/=(Wint &a,const Wint &b)
{
return a=a/b;
}
Wint& operator%=(Wint &a,const Wint &b)
{
divmod(a,b);
return a;
}
Wint operator%(Wint a,const Wint &b)
{
return a%=b;
}
//順手實現一個快速冪,可以看到和普通快速冪幾乎無異
Wint pow(const Wint &n,const Wint &k)
{
if(k.empty())return 1;
if(k==2)return n*n;
if(k.back()%2)return n*pow(n,k-1);
return pow(pow(n,k/2),2);
}
//通過過載運算子,還可以實現++、--、^、!、邏輯運算子等很多運算,十分簡單,此處都不寫了
int main()//現在你完全可以像int一般便捷地使用Wint,如下
{
Wint a,b;
//可以把b改成int型,仍能正常使用
cin>>a>>b;
cout<<(a<b)<<endl
<<(a==b)<<endl
<<a+b<<endl
<<a-b<<endl
<<a*b<<endl
<<a/b<<endl
<<a%b<<endl
<<pow(a,b);
}
大數除法
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int L=110;
int sub(int *a,int *b,int La,int Lb)
{
if(La<Lb) return -1;//如果a小於b,則返回-1
if(La==Lb)
{
for(int i=La-1;i>=0;i--)
if(a[i]>b[i]) break;
else if(a[i]<b[i]) return -1;//如果a小於b,則返回-1
}
for(int i=0;i<La;i++)//高精度減法
{
a[i]-=b[i];
if(a[i]<0) a[i]+=10,a[i+1]--;
}
for(int i=La-1;i>=0;i--)
if(a[i]) return i+1;//返回差的位數
return 0;//返回差的位數
}
string div(string n1,string n2,int nn)//n1,n2是字串表示的被除數,除數,nn是選擇返回商還是餘數
{
string s,v;//s存商,v存餘數
int a[L],b[L],r[L],La=n1.size(),Lb=n2.size(),i,tp=La;//a,b是整形陣列表示被除數,除數,tp儲存被除數的長度
fill(a,a+L,0);fill(b,b+L,0);fill(r,r+L,0);//陣列元素都置為0
for(i=La-1;i>=0;i--) a[La-1-i]=n1[i]-'0';
for(i=Lb-1;i>=0;i--) b[Lb-1-i]=n2[i]-'0';
if(La<Lb || (La==Lb && n1<n2)) {
//cout<<0<<endl;
return n1;}//如果a<b,則商為0,餘數為被除數
int t=La-Lb;//除被數和除數的位數之差
for(int i=La-1;i>=0;i--)//將除數擴大10^t倍
if(i>=t) b[i]=b[i-t];
else b[i]=0;
Lb=La;
for(int j=0;j<=t;j++)
{
int temp;
while((temp=sub(a,b+j,La,Lb-j))>=0)//如果被除數比除數大繼續減
{
La=temp;
r[t-j]++;
}
}
for(i=0;i<L-10;i++) r[i+1]+=r[i]/10,r[i]%=10;//統一處理進位
while(!r[i]) i--;//將整形陣列表示的商轉化成字串表示的
while(i>=0) s+=r[i--]+'0';
//cout<<s<<endl;
i=tp;
while(!a[i]) i--;//將整形陣列表示的餘數轉化成字串表示的</span>
while(i>=0) v+=a[i--]+'0';
if(v.empty()) v="0";
//cout<<v<<endl;
if(nn==1) return s;
if(nn==2) return v;
}
int main()
{
string a,b;
while(cin>>a>>b){
cout<<div(a,b,1)<<endl;
cout<<div(a,b,2)<<endl;
}
return 0;
}
大數+ - *
#include<iostream>
#include<string>
#include<algorithm>
#include<sstream>
using namespace std;
//string轉換為int
int strint(string s) {
int num;
stringstream ss(s);
ss >> num;
return num;
}
//int轉換為string
string intstr(int num) {
string s;
stringstream ss;
ss << num;
ss >> s;
return s;
}
//前置0 ,因為大數的長度必須要為2^n的倍數,才能劃分
void removePrezero(string &s) {
if (s.length() == 1)return;
int k = 0;
for (int i = 0; i < s.length(); i++) {
if (s[i] == '0')k++;
else break;
}
if (k == s.length())s = "0";
else s = s.substr(k);
}
//大數相加
string add(string s1, string s2) {
string s = "";
removePrezero(s1); //去掉前置0
removePrezero(s2);
reverse(s1.begin(), s1.end()); //先把字串顛倒,方便相加
reverse(s2.begin(), s2.end());
int c = 0;
for (int i = 0;c|| i < max(s1.length(), s2.length()); i++) {
int t = c;
if (i < s1.length())t += s1[i] - '0';
if (i < s2.length())t += s2[i] - '0';
int d = t % 10;
s.insert(0, intstr(d));
c = t / 10;
}
return s;
}
//大數相減
string subtra(string &s1, string &s2) {
string s = "";
string flag;
removePrezero(s1); //去掉前置0
removePrezero(s2);
int len1 = s1.length();
int len2 = s2.length();
int len = len1>len2 ? len1 : len2;
if (len1 < len2)flag = "-";
else if (len1 > len2)flag = "+";
else {
int i;
for (i = 0; i < len1; i++) {
if (s1.at(i) > s2.at(i)) {
flag = "+"; break;
}
else if (s1.at(i) < s2.at(i)) {
flag = "-"; break;
}
}
if (i == len1)s == "0";
}
int* num = (int*)malloc(sizeof(int)*len);
reverse(s1.begin(), s1.end()); //方便相減
reverse(s2.begin(), s2.end());
int c = 0;
for (int j = 0; j < len; j++) {
int n1 = j < len1 ? s1[j] - '0' : 0;
int n2 = j < len2 ? s2[j] - '0' : 0;
if (flag == "+")num[c++] = n1 - n2;
else num[c++] = n2 - n1;
}
for (int j = 0; j < c; j++) {
if (num[j] < 0) {
num[j] += 10; num[j + 1] -= 1;
}
}
c--;
while (num[c] == 0)c--;
for (int j = 0; j <=c; j++){
s.insert(0, intstr(num[j]));
}
if (flag == "-")return flag + s;
else return s;
}
//增加前置0
void addPrezero(string &s, int L) {
for (int i = 0; i < L; i++)
s = s.insert(0, "0");
}
//增加後置0,大數*10^n 相當於在數的後面加n個0
string addLastzero(string s, int L) {
string s1 = s;
for (int i = 0; i < L; i++)
s1 += "0";
return s1;
}
//大數相乘
string multi(string &s1, string &s2) {
bool flag1 = false, flag2 = false;
string sign; //作用是判斷結果是正數還是負數
if (s1.at(0) == '-') {
flag1 = true; s1 = s1.substr(1);
}
if (s1.at(0) == '-') {
flag2 = true; s2 = s2.substr(1);
}
if (flag1&&flag2)sign = "+";
else if (flag1 || flag2) sign = "-";
else sign = "+";
int L = 4; //將數前置若干個0,使其長度為2^n的倍數
if (s1.length() > 2 || s2.length() > 2) {
if (s1.length() >= s2.length()) {
while (L < s1.length())L *= 2;
if (L != s1.length())
addPrezero(s1, L - s1.length());
addPrezero(s2, L - s2.length());
}else {
while (L < s2.length())L*=2;
if (L != s2.length())
addPrezero(s2, L - s2.length());
addPrezero(s1, L - s1.length());
}
}
if (s1.length() == 1)addPrezero(s1, 1);
if (s2.length() == 1)addPrezero(s2, 1);
int n = s1.length();
string result, a0, a1, b0, b1;
if (n > 1) {
a1 = s1.substr(0, n / 2);
a0 = s1.substr(n / 2, n);
b1 = s2.substr(0, n / 2);
b0 = s2.substr(n / 2, n);
}
if (n == 2) {
int x1 = strint(a1);
int x2 = strint(a0);
int y1 = strint(b1);
int y2 = strint(b0);
int num = (x1 * 10 + x2)*(y1 * 10 + y2);
result = intstr(num);
}else {
string c2 = multi(a1, b1);
string c0 = multi(a0, b0);
string temp1 = add(a0, a1);
string temp2 = add(b1, b0);
string temp3 = add(c2, c0);
string temp_c1 = multi(temp1, temp2);
string c1 = subtra(temp_c1, temp3);
string s1 = addLastzero(c1, n / 2);
string s2 =addLastzero(c2, n);
result = add(add(s1, s2), c0);
}
if (sign == "-")result.insert(0, sign);
return result;
}
int main() {
//text
string s1 = "-1234999999999999999999999", s2 = "12348976543";
cout << multi(s1, s2);
}
判斷大數是否為素數
#include<iostream>
#include<ctime>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1000000+10;
ll mul(ll a, ll b, ll m)
//求a*b%m
{
ll ans = 0;
a %= m;
while(b)
{
if(b & 1)ans = (ans + a) % m;
b /= 2;
a = (a + a) % m;
}
return ans;
}
ll pow(ll a, ll b, ll m)
//a^b % m
{
ll ans = 1;
a %= m;
while(b)
{
if(b & 1)ans = mul(a, ans, m);
b /= 2;
a = mul(a, a, m);
}
ans %= m;
return ans;
}
bool Miller_Rabin(ll n, int repeat)//n是測試的大數,repeat是測試重複次數
{
if(n == 2 || n == 3)return true;//特判
if(n % 2 == 0 || n == 1)return false;//偶數和1
//將n-1分解成2^s*d
ll d = n - 1;
int s = 0;
while(!(d & 1)) ++s, d >>= 1;
srand((unsigned)time(NULL));
for(int i = 0; i < repeat; i++)//重複repeat次
{
ll a = rand() % (n - 3) + 2;//取一個隨機數,[2,n-1)
ll x = pow(a, d, n);
ll y = 0;
for(int j = 0; j < s; j++)
{
y = mul(x, x, n);
if(y == 1 && x != 1 && x != (n - 1))return false;
x = y;
}
if(y != 1)return false;//費馬小定理
}
return true;
}
int main()
{
int T;
cin >> T;
ll n;
while(T--)
{
cin >> n;
if(Miller_Rabin(n, 50))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
相關文章
- 【數學問題】判斷一個數是否是素數
- 判斷素數
- 素數判斷
- 三個數字的加減乘除模運算
- 判斷一個數是否為質數(程式碼)
- linux 中如何判斷變數是否為數值Linux變數
- postgresql判斷是否為數字的方法SQL
- 超大整數的加減乘除計算方法
- 與數論的愛恨情仇--01:判斷大素數的Miller-Rabin
- JavaScript判斷數字是否是質數JavaScript
- Python:判斷一個正整數是否為迴文數Python
- Python判斷字串是否為字母或者數字(浮點數)Python字串
- C語言判斷素數,判斷質素演算法C語言演算法
- 浮點數的加減乘除運算細節
- JavaScript浮點數加減乘除精確計算JavaScript
- L1-028 判斷素數 分數 10
- 【質數判斷】給定兩個數,判斷這兩個數是否互質?
- C++筆記:輸入輸出、變數、變數加減乘除C++筆記變數
- python如何判斷一個數是否是整數Python
- java判斷輸入的字串是否為數字Java字串
- 位運算-判斷一個數是否為2的整數次方
- go 如何優雅的判斷變數是否為 nilGo變數
- 判斷一個數是不是質數(素數),3種方式介紹
- wenbao與篩法素數及判斷模板
- JavaScript 判斷變數是否是函式JavaScript變數函式
- 判斷自身開方是否是整數
- JavaScript判斷兩個變數是否相等JavaScript變數
- 接收使用者輸入的數字,判斷該數字是否為四葉玫瑰數
- Python判斷變數是否是整數的方法有哪些?Python變數
- nginx判斷路徑是否含有某個引數做判斷Nginx
- isAlnum判斷字元是否為字母數字字元(字母和數字都屬於字母數字字元)字元
- 密碼工程-大素數密碼
- 正規表示式判斷是否是數字
- <Python>判斷變數是否是DataFrame 或者 SeriesPython變數
- Python中判斷是否為數字字串的方法是什麼?Python字串
- SQL 判斷欄位是否以數字開頭或者包含數字SQL
- 每日codewars題之判斷一個數是否是水仙花數
- vue.js判斷網址引數是否有效Vue.js