自我感受良好的大數模擬

從前的大數模擬都是本身用字符串來敲的,忽然看到同窗的代碼後釋放了不少思惟,不只敲得快還不容易錯,因而找個晚上敲下大數的一些模擬,留下板子記錄一下.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;
}
相關文章
相關標籤/搜索