從前的大數模擬都是本身用字符串來敲的,忽然看到同窗的代碼後釋放了不少思惟,不只敲得快還不容易錯,因而找個晚上敲下大數的一些模擬,留下板子記錄一下.c++
對於負數加減模擬運算
咱們能夠分狀況討論並編寫另外一個函數,即:數組
ans = add(a,b)
ans = '-' + add(a,b)
ans = sub(a,b)
or ans = sub(b,a)
可擬函數函數
string add_op(string a,string b) { string ans; if(a[0] == '-' && b[0] == '-'){ a.erase(a.begin()); b.erase(b.begin()); ans = '-' + big_add(a,b); } else if(a[0] == '-'){ a.erase(a.begin()); ans = big_sub(b,a); } else if(b[0] == '-'){ b.erase(b.begin()); ans = big_sub(a,b); } else{ ans = big_add(a,b); } return ans; }
//不支持負數 const int MAXN = 1e8 + 10; int t[MAXN]; string big_add(string a,string b){ int len1 = a.size(); int len2 = b.size(); reverse(a.begin(),a.end()); //調換順序方便處理 reverse(b.begin(),b.end()); if(len1 < len2){ swap(a,b); //令a是數位較長的數 swap(len1,len2); } for(int i = 0;i < len2;++i){ //t數組存在第i位上兩數相加的結果,暫時不進位 t[i] = a[i] -'0' + b[i] - '0'; } for(int i = len2;i < len1;++i){ t[i] = a[i] - '0'; } int flag = 0; //flag 標誌是否須要進位 for(int i = 0;i < len1;++i){ if(flag) { t[i]++; flag = 0; } if(t[i] >= 10){ t[i]-=10; flag = 1; } } if(flag) t[len1] = 1; //處理最高位是否須要進位,若不須要令最高位爲 0 else t[len1] = 0; string ans; flag = 0; for(int i = len1;i >= 0 ;--i){ //去除前導0 if( flag == 0 && t[i] == 0) continue; flag = 1; ans.push_back(t[i] + '0'); } if(ans.empty()) ans.push_back('0'); return ans; }
const int MAXN = 1e8 + 10; int t[MAXN]; string big_sub(string a,string b) { string ans; int len1 = a.size(); int len2 = b.size(); reverse(a.begin(),a.end()); //調換順序便於處理 reverse(b.begin(),b.end()); for(int i = 0;i < len2 ;++i){ //t數組保存第i位上兩數之差 t[i] = a[i] - b[i]; } for(int i = len2;i < len1;++i){ t[i] = a[i] - '0'; //若a位數較長,則長度超過b的位結果爲a[i] - 0 } int flag = 0; for(int i = 0;i < len1;++i){ //借位 if(flag){ flag = 0; t[i]--; } if(t[i] < 0){ t[i]+=10; flag = 1; } } flag = 0; for(int i = len1-1;i >= 0;--i){ //去除前導0 if(!flag && t[i] == 0) continue; flag = 1; ans.push_back(t[i] + '0'); } if(ans.empty()) ans.push_back('0'); //若結果爲0,答案 ans = 0 return ans; }
int t[10000000]; string mul(string a,string b) { reverse(a.begin(),a.end()); //交換順序,方便計算 reverse(b.begin(),b.end()); int len1=a.size(); int len2=b.size(); for(int i = 0;i < len1;++i) for(int j = 0;j < len2;++j) t[i+j]=(a[i]-'0')*(b[j]-'0')+t[i+j]; //先總體乘起來,不進位 t[len1 + len2 -1] = 0; //進位 for(int i = 0;i < len1 + len2;++i){ t[i+1] += t[i] / 10; t[i] %= 10; } int x = len1 + len2; //結果最長的位數 if(t[len1 + len2-1] == 0) x--; string ans = ""; int flag = 1; //flag用來作作去除前導零的標記 for(int i = x-1;i >= 0;--i){ if(t[i] == 0 && flag) { continue; } flag = 0; ans.push_back(t[i] + '0'); } if(ans.empty()) ans.push_back('0'); //若結果爲零,返回"0" return ans; }
//大數求模就很簡單了,根據同餘定理來按位求模就行了 long long big_mod(string a,long long mod) { int len=a.size(); long long ans=0; for(int i=0;i<len;++i) ans=(ans*10%mod+a[i]-'0')%mod; return ans; }
//還不太會,先留個板子(留坑) #include<bits/stdc++.h> using namespace std; const int mod = 1e9 + 7; typedef long long ll; ll phi(ll n) { int ans = n, temp = n; for (int i = 2; i*i <= temp; i++) { if (temp%i == 0) { ans -= ans / i; while (temp%i == 0) temp /= i; } } if (temp > 1) ans -= ans / temp; return ans; } ll mod_pow(ll x, ll n, ll mod) //快速冪 { ll ans = 1; while (n) { if (n % 2 == 1) ans = ans * x%mod; x = x * x%mod; n /= 2; } return ans; } char a[1000010],b[1000010]; int main() { scanf("%s%s", a, b); ll phic = phi(mod); int i, len = strlen(a); ll res = 0, ans; for (i = 0; i < len; i++) { res = res * 10 + a[i] - '0'; if (res > phic) break; } if (i == len) { ans = mod_pow(2, res, mod) % mod; } else { res = 0; for (int i = 0; i < len; i++) { res = res * 10 + a[i] - '0'; res %= phic; } ans = mod_pow(2, res + phic, mod) % mod; } cout << ans << endl; return 0; }