• 洛谷 P1045 【麦森数】快速幂


    不用快速幂,压位出奇迹!

    本人是个蒟蒻,不太熟悉快速幂,这里给大家介绍一种压位大法。

    让我们来分析一下题目,第一位是送分的,有一个专门求位数的函数:n*log10(2)+1。 然后题目中p<=3100000,又要求后500位,普通算法肯定超时,但如果我们多压几位甚至时间都比普通快速幂少。而且我们用 long long 的话可以一次就乘上2的20次方又能节省时间;

    第一问:

    s=n*log10(2)+1;用函数算位数 
    cout<<s<<endl;
    

    第二问:算后500位:

    while(n>=20){
            k=0;
            for(i=1;i<=50||i<=top;i++){//数组的每一个元素里放十位数 
                a[i]=a[i]*1048576+k;//每次乘上2的20次方:“1048576”把longlong剩余9位用到位 
                k=a[i]/ya;a[i]%=ya;//进位 
                if(top<50&&k&&i==top)top++;//加位数 
            }
            n-=20;//一次算20个 
        }
    

    注意:n<20时还需要还需要用一次乘2的循环!

    小于500位要加前导零:

    while(i<=50){//小于500位,要加前导零 
                for(j=1;j<=5&&i<=50;i++,j++)cout<<"0000000000";//补10个0
                if(j==6)cout<<endl;
            }
    

    大于500位的情况:

    while(i>=1){//注意:大于五百位也有可能有前导零 
                for(j=1;j<=5&&i>=1;i--,j++){//是每一个元素(10位)中的的前导零
                    if(a[i]>1000000000)cout<<a[i];//判断是否有前导零 
                    else{
                        s=a[i];
                        while(s>0){s/=10;o++;}//记录前导零个数 
                        o=10-o;
                        while(o>0){o--;cout<<"0";}//输出 
                        cout<<a[i];
                    }
                }
                cout<<endl;
            }
    

    完整代码:(因为有些情况会重复,代码会有点长)

    #include<iostream>
    #include<cmath>
    using namespace std;
    long long a[51]={0,1},n,i,j,o,s,k,top=1;
    int main(){
        cin>>n;
        s=n*log10(2)+1;//用函数算位数 
        cout<<s<<endl;
        while(n>=20){
            k=0;
            for(i=1;i<=50&&i<=top;i++){//数组的每一个元素里放十位数 
                a[i]=(a[i])<<20+k;//每次乘上2的20次方:1048576 把longlong剩余9位用到位 
                k=a[i]/10000000000;a[i]%=10000000000;//进位 
                if(top<50&&k&&i==top)top++;//加位数 ,前面s算过了 可以省 
            }
            n-=20;//一次算20个 
        }
        while(n){//把20个以下的依次算完 
            k=0;
            for(i=1;i<=50&&i<=top;i++){
                a[i]=a[i]<<1+k;
                k=a[i]/10000000000;a[i]%=10000000000;//用法同上 
                if(top<50&&k&&i==top)top++;
            }
            n--;
        }
        a[1]--;
        if(top<50){
            i=top+1;//可以用s 
            while(i<=50){//小于500位,要加前导零 
                for(j=1;j<=5&&i<=50;i++,j++)cout<<"0000000000";
                if(j==6)cout<<endl;
            }
            i=top;
            for(;j<=5&&i>=1;i--,j++){//注意:50位一行!!!j<=5!!! 
                if(a[i]>=1000000000)cout<<a[i];
                else{
                    s=a[i];
                    while(s>0){s/=10;o++;}
                    o=10-o;
                    while(o>0){o--;cout<<"0";}
                    cout<<a[i];
                }
            }
            cout<<endl;
            while(i>=1){//注意:大于五百位也有可能有前导零 
                for(j=1;j<=5&&i>=1;i--,j++){//是每一个元素(10位)中的的前导零
                    if(a[i]>1000000000)cout<<a[i];//判断是否有前导零 
                    else{
                        s=a[i];
                        while(s>0){s/=10;o++;}//记录前导零个数 
                        o=10-o;
                        while(o>0){o--;cout<<"0";}//输出 
                        cout<<a[i];
                    }
                }
                cout<<endl;
            }
        }
        else{
            s=a[50];
            i=50;
            while(i>=1){
                for(j=1;j<=5&&i>=1;i--,j++){
                    if(a[i]>1000000000)cout<<a[i];
                    else{
                        s=a[i];
                        while(s>0){s/=10;o++;}//      这一段用法同上 
                        o=10-o;
                        while(o>0){o--;cout<<"0";}
                        cout<<a[i];
                    }
                }
                cout<<endl;
            }
        }
        return 0;
    }
    

    啊,好长啊,压位果然有副作用。

    这是我的博客,发的题解和一些洛谷技巧都在里面。

    另外,本人真的只是一个弱弱的萌新,7月份才入信息组,发的题解讨论等级不高,新人可看。

    ✐☎博主撰文不易,转载还请注明出处;若对本文有疑,请私信或在下方讨论中提出。O(∩_∩)O谢谢!☏

    ☃〔尽管小伙伴们肯定有千百种方式针对,但博主还是极其非常十分不要脸的把反对键吃掉辣!〕☃

    ✿『$At$ $last$:非常一(hu)本(shuo)正(ba)经(dao)的:博主很笨,请不要欺负他』✿✍

  • 相关阅读:
    开源.net 混淆器ConfuserEx介绍
    k8s删除namespace失败,状态Terminating解决方案
    java get all threadlocal from thread
    mysql查看索引的大小
    InnoDB一定会在索引中加上主键吗?
    全链路追踪traceId,ThreadLocal与ExecutorService
    redis 批量删除keys
    shell逐行读取excel并执行sql
    Is it possible to create @Around Aspect for feign.Client
    Spring Boot后台启动不打印nohup.out
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/9879226.html
Copyright © 2020-2023  润新知