zoukankan      html  css  js  c++  java
  • 十进制快速幂

    十进制快速幂

    使用快速幂求aba^b, 当bb很大的时候, 就需要使用十进制快速幂

    十进制快速幂

    aba^bbb可以分解为 kn10n+kn110n1+...+k1k_n 10^n + k_{n-1}10^{n-1} + ... + k_1
    则可以得到 ab=akn10nakn110n1.....ak1a^b=a^{k_n10^n}*a^{k_{n-1}10^{n-1}} *.....a^{k_1}
    在十进制快速幂中, 将a1a^1作为基底, 采用从低位到高位处理的办法, 对于每个位数上的数字, 只要有a2,a3,a4a^2, a^3, a^4, 即可凑出所有1010以内的所有幂数, 在进入下一个更高位的时候, 将当前基底aba^b ->ab10a^{b*10}即可

    我们以 求 2N1N2^{N-1} * N 为例子得到以下代码
    在代码中有KSM1KSM_1KSM2KSM_2两个函数, 作用是一样的, 其中1的效率比2更快, 大概 1/31/3

    Code

    #include<bits/stdc++.h>
    #define reg register
    
    typedef long long ll;
    
    const int mod = 1e9;
    const int maxn = 1e7+5;
    
    char S[maxn];
    int Len;
    
    ll KSM(ll a, ll b){
            ll s = 1;
            while(b){
                    if(b & 1) s = s*a % mod;
                    a = a*a % mod;
                    b >>= 1;
            }
            return s;
    }
    
    ll KSM_1(ll a){
            ll s = 1;
            for(reg int i = 1; i <= Len; i ++){
                    ll t2 = a*a % mod;
                    ll t3 = t2 * a % mod;
                    ll t4 = t3 * a % mod;
                    ll t5 = t4 * a % mod;
                    if(S[i] == '1') s = s * a % mod;
                    else if(S[i] == '2') s = s * t2 % mod;
                    else if(S[i] == '3') s = s * t3 % mod;
                    else if(S[i] == '4') s = ((s*a % mod) * t3) % mod;
                    else if(S[i] == '5') s = ((s*t2 % mod) * t3) % mod;
                    else if(S[i] == '6') s = ((s*t3 % mod) * t3) % mod;
                    else if(S[i] == '7') s = ((s*t3 % mod) * t4) % mod;
                    else if(S[i] == '8') s = ((s*t4 % mod) * t4) % mod;
                    else if(S[i] == '9') s = ((s*t4 % mod) * t5) % mod;
                    a = t5 * t5 % mod;
            }
            return s;
    }
    
    ll KSM_2(ll a){
            ll s = 1;
            for(reg int i = 1; i <= Len; i ++){
                    int p = S[i] - '0';
                    while(p --) s = s * a % mod;
                    p = 9;
                    ll tmp = a;
                    while(p --) a = a * tmp % mod;
            }
            return s;
    }
    
    int main(){
            scanf("%s", S+1);
            Len = strlen(S+1);
            ll Temp = 0;
            for(reg int i = 1; i <= Len; i ++) Temp = (Temp*10+S[i]-'0') % mod;
    
            std::reverse(S+1, S+Len+1);
            int t = 1;
            while(S[t] == '0') S[t ++] = '9';
            S[t] --;
            if(S[Len] == '0') Len --;
            //printf("%lld
    ", Temp);
            printf("%lld
    ", KSM_2(2) * Temp % mod);
            return 0;
    }
    
    

    既然有十进制快速幂, 肯定会有十进制矩阵快速幂,道理是一样的, 代码如下

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    const int mod = 998244353;
    
    int L;
    char N[4005];
    
    namespace mt{   
        struct matrix{
            int C[10][10];
            matrix(){ memset(C, 0, sizeof C); }
        };
    
        matrix mdf(matrix a, matrix b){
            matrix s;
            for(int i = 1; i <= 6; i ++)
                for(int j = 1; j <= 6; j ++)
                    for(int k = 1; k <= 6; k ++)
                        (s.C[i][k] += (long long)a.C[i][k] * b.C[k][i] % mod) %= mod;
            return s;
        }
    
        matrix Counting(matrix a){
            matrix s;
            for(int i = 1; i <= 6; i ++) s.C[i][i] = 1;
            while(L --){
                matrix B = mdf(a, a);   //a^2
                matrix C = mdf(B, a);   //a^3
                matrix D = mdf(C, a);   //a^4
                switch(N[L]){
                    case '1':{ s = mdf(s, a); break ; }
                    case '2':{ s = mdf(s, B); break ; }
                    case '3':{ s = mdf(s, C); break ; }
                    case '4':{ s = mdf(s, D); break ; }
                    case '5':{ s = mdf(mdf(D, a), s); break ; }
                    case '6':{ s = mdf(mdf(B, D), s); break ; }
                    case '7':{ s = mdf(mdf(C, D), s); break ; }
                    case '8':{ s = mdf(mdf(D, D), s); break ; }
                    case '9':{ s = mdf(mdf(mdf(D, a), D), s); break ; }
                }
                a = mdf(mdf(mdf(a, D), D), B);
            }
            return s;
        }
    }
    
    mt::matrix I;
    
    int main(){
        scanf("%s", N + 1);
        L = strlen(N + 1);
        if(L == 1 && N[L] <= '4')
            switch(N[L]){
                case '1':{ puts("1"); return 0; }
                case '2':{ puts("3"); return 0; }
                case '3':{ puts("10"); return 0; }
                case '4':{ puts("23"); return 0; }
            }
    
        return 0;
    }
    
  • 相关阅读:
    SQL去除重复记录
    FullCalendar应用——整合农历节气和节日
    Dropzone.js实现文件拖拽上传
    HTML5实现文件断点续传
    FullCalendar日历插件说明文档
    网络电影免会员播放器
    百度网盘搜索工具
    HTML5学习
    HTML2 -- 布局格式
    JS10 -- url问号后的数据
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822674.html
Copyright © 2011-2022 走看看