• P1045 [NOIP2003 普及组] 麦森数


    https://www.luogu.com.cn/problem/P1045

    首先第一问,输出(2^p-1) 的位数

    (1)自然数(n)的位数计算公式推导
    (n=10) 位数是(2);
    (n=100) 位数是(3);
    (n=1000) 位数是(4);
    (n=12345) 位数是(5);
    小结:自然数(n)的位数等于(lfloor log_{10}(n) floor +1),就也是 (lfloor lg(n)+1 floor)

    对数与指数的知识

    cout << log10(12345) << endl;        //求10的多少次方是12345
    cout << pow(10, 4.09149) << endl; //输出12345 ,表示10的4.09149次方是12345。
    

    以上面的例子来说,(lg(12345)+1= lfloor lg(12345) floor +1=lfloor 4.09149 floor +1)=(4+1)=(5)

    至此,问题转化为求:(lg(2^p-1)+1)的值 。

    (2)(2^p-1)的位数与(2^p)位数的关系
    考虑到(2^p)的个位只能是(2,4,6,8),不可能出现数字(0),所以(2^p-1)的位数与(2^p)位数是一样的。也就是说,我们只需要计算出(lg(2^p)+1)就可以知道答案了!

    (3)计算(lg(2^p)+1)
    这个玩意怎么算呢?利用数学公式(lg(m^n)=m * lg(n))来算,就是(p* lg(2)+1),而(lg(2))就是以(10)为底的(2)的对数,C++中有现成的计算函数(int) (p * log10(2) + 1)

    #include <bits/stdc++.h>
    using namespace std;
    
    /*
    vector resize解析:
    如果n小于当前容器的大小,则将内容减少到其前n个元素,并删除超出范围的元素(并销毁它们)。
    如果n大于当前容器的大小,则通过在末尾插入所需数量的元素来扩展内容,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则将对它们进行值初始化。
    如果n也大于当前容器容量,将自动重新分配已分配的存储空间。
    请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。
    */
    
    //高精度乘法模板(高精乘高精)
    vector<int> mul(vector<int> &A, vector<int> &B) {
        //只保留500个长度
        if(A.size()>500) A.resize(500);    
        if(B.size()>500) B.resize(500);
    
        int la = A.size(), lb = B.size();
        vector<int> C(la + lb + 10, 0);//提前申请结果所需的空间
        for (int i = 0; i < la; i++)
            for (int j = 0; j < lb; j++)
                C[i + j] += A[i] * B[j];
    
        for (int i = 0; i < C.size(); i++)
            if (C[i] >= 10) {
                C[i + 1] += C[i] / 10;
                C[i] %= 10;
            }
        //处理前导0
        while (C.size() > 1 && C.back() == 0)C.pop_back();
    
        //只保留500个长度
        if(C.size()>500) C.resize(500);
        return C;
    }
    
    //快速幂+高精度 a^b
    vector<int> qmi(int a, int b) {
        vector<int> ans;
        ans.push_back(1);
    
        vector<int> A;
        A.push_back(a);
        while (b) {
            if (b & 1) ans = mul(ans, A);
            b >>= 1;
            A = mul(A, A);
        }
        return ans;
    }
    
    int main() {
        int p;
        cin >> p;
        vector<int> A = qmi(2, p);
    
        vector<int> B;
        B.push_back(1);
    
        A[0]--;
    
        //一共多少位
        printf("%d
    ", (int) (p * log10(2) + 1));
    
        //每行输出50位,共输出10行,不足500位时高位补0
        int cnt = A.size();
        for (int i = 0; i < 500 - cnt; i++) A.push_back(0);
    
        //倒着输出
        for (int i = 500 - 1; i >= 0; i--) {
            printf("%d", A[i]);
            if (i % 50 == 0 && i < A.size() - 1) printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    linux 中的vim的配置文件的位置
    centos find
    multi-cursor
    ctrlsf插件
    Vim的可视模式
    Vim的tagbar插件
    Vim的tag系统
    ~/.ctag的作用与配置
    在Vim里使用gtags-cscope
    查看Vim的option变量的值
  • 原文地址:https://www.cnblogs.com/littlehb/p/14991080.html
Copyright © 2020-2023  润新知