• 麦森数(分治或快速幂)


    分治: 麦森数的解题报告

    题目分析:

    第一问是很简单的,只需要求一个对数而已,数学原理:十进制正整数n的位数为int(log10(n))+1。所以2^P-1的位数int(log10(2)*p)+1 。

    2^p = 10^(p*log10(2) )   , 所以2^p的位数是p*log10(2)。

    第二问的关键是高精度乘法和指数幂的运算,而且由于题目要求最后500位数字,所以在计算乘法的时候我们只要求计算乘数的低500位就好了。

    指数幂的运算不能硬乘,而要采用分治算法,否则就超时了。分治递归算法求指数幂是非常经典的,其数学原理是a^n = a^(n/2)*a^(n/2)*f(a),其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)。

    另外我们也可以创建一个栈,记录每次执行(n /= 2)前n的值是奇数还是偶数,然后根据上面的数学原理,模仿递归的思路,从n=1或n=0开始逆向计算a^n。

    采用递归算法的时候,由于存储高精度整数数组的大小是预置MAX = 1000,所以在调用递归函数的时候要按引用传递参数,否则到了后面空间就不够分配了。

    为了满足“每行输出50位”的条件,我把存储高精度整数数组的元素设置成5位数,这样输出的时候只需每行输出10个元素就行了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include <cctype>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<string>
     8 #include<cmath>
     9 #include<set>
    10 #include<vector>
    11 #include<stack>
    12 #include<queue>
    13 #include<map>
    14 using namespace std;
    15 #define ll long long
    16 #define mem(a,x) memset(a,x,sizeof(a))
    17 #define se second
    18 #define fi first
    19 const int INF= 0x3f3f3f3f;
    20 const int N=1e6+5;
    21 
    22 int p,a[505],b[1005];
    23 
    24 void quick(int x)
    25 {
    26     if(x==0) return;
    27     quick(x/2);
    28     mem(b,0);    
    29     for(int i=0;i<500;i++)
    30     {
    31         for(int j=0;j<500;j++)
    32         {
    33             if(x&1)     b[i+j] += a[i]*a[j]*2;
    34             else   b[i+j] += a[i]*a[j];
    35         }
    36     }
    37     for(int i=0;i<500;i++)
    38     {
    39         a[i] = b[i]%10;
    40         b[i+1]+= b[i]/10;
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     cin>>p;
    47     a[0]=1;
    48     quick(p);
    49     
    50     a[0]--;
    51     int k=0;
    52     while(a[k]<0) a[k+1]--,a[k]+=10,k++;
    53     
    54     cout<< floor( p*log10(2)+1 )<<endl;
    55     for(int i=499;i>=0;i--)
    56     {
    57         cout<<a[i];
    58         if((i)%50==0) cout<<endl;
    59     }
    60 }

    接下来 套一套快速幂的模板。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include <cctype>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<string>
     8 #include<cmath>
     9 #include<set>
    10 #include<vector>
    11 #include<stack>
    12 #include<queue>
    13 #include<map>
    14 using namespace std;
    15 #define ll long long
    16 #define mem(a,x) memset(a,x,sizeof(a))
    17 #define se second
    18 #define fi first
    19 const int INF= 0x3f3f3f3f;
    20 const int N=1e6+5;
    21 
    22 int p,a[1005],b[1005],c[1005],f[1005],d[1005];
    23 
    24 void work1()
    25 {
    26     mem(c,0);
    27     for(int i=0;i<500;i++)
    28     {
    29         for(int j=0;j<500;j++)
    30         {
    31             c[i+j] += a[i]*b[j];  //数组a就是原来快速幂模板中的ans, 数组b就是a 
    32         }
    33     }
    34     for(int i=0;i<500;i++)
    35     {
    36         f[i]=c[i]%10;
    37         c[i+1]+=c[i]/10;
    38         a[i]=f[i]; //更新a数组,即实现ans*=a的步骤 得到ans*=a后的ans 
    39     }
    40 }
    41 void work2()
    42 {
    43     mem(d,0);
    44     for(int i=0;i<500;i++)
    45     {
    46         for(int j=0;j<500;j++)
    47         {
    48             d[i+j] += b[i]*b[j];
    49         }
    50     }
    51     for(int i=0;i<500;i++)
    52     {
    53         b[i]=d[i]%10;  //更新b数组,即实现 a*=a的步骤 
    54         d[i+1]+=d[i]/10;
    55     }
    56 }
    57 
    58 void quick(int x,int y)
    59 {
    60     a[0]=1;  //ans  相当于给ans赋初值1 
    61     b[0]=x; // a  给a赋初值 2
    62     while(y)
    63     {
    64         if(y&1) work1();
    65         y>>=1;
    66         work2();
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     cin>>p;
    73     quick(2,p);
    74     
    75     f[0]--; int k=0;
    76     while(f[k]<0) f[k]+=10,f[k+1]--,k++;
    77     
    78     cout<<floor(p*log10(2)+1) <<endl;
    79     for(int i=499;i>=0;i--)
    80     {
    81         cout<<f[i];
    82         if(i%50==0) cout<<endl;
    83     }
    84     
    85 }
  • 相关阅读:
    RF简介
    ADB & FASTBOOT COMMAND ON WINDOWS
    通过Mac电脑安装apk 和 ipa到安卓和苹果手机
    Mac搭建移动端自动化环境遇到的node安装失败的坑与解决方法
    Git 连接pycharm
    Appium环境搭建和命令
    穿戴设备(智能手表)移动端测试浅谈1
    IOS UIImageView的contentMode属性
    IOS OC数据类型
    IOS textField(textview)字数判断
  • 原文地址:https://www.cnblogs.com/thunder-110/p/9389914.html
Copyright © 2020-2023  润新知