• OpenJudge NOI 1.13 49:计算对数


    【题目链接】

    OpenJudge NOI 1.13 49:计算对数

    【题目考点】

    1. 高精度

    • 高精乘高精

    2. 枚举

    【解题思路】

    解法1:枚举

    由于题目中说了,x不大于20,所以只需要枚举20以内的x,看取哪一个x时满足 a x ≤ b < a x + 1 a^x\le b < a^{x+1} axb<ax+1即可。
    这里需要高精度数字比较、高精度乘高精度。
    a最多100位,x最高20,得到的数字 a x + 1 a^{x+1} ax+1最大不会超过2100位。
    记n为数字a的位数,该算法复杂度为: O ( n x + 1 ) O(n^{x+1}) O(nx+1)

    解法2:二分

    假设x可以很大,那么需要用二分查找来确定x的值。使用快速幂来求 a x a^x ax
    设l为1,r为20,每次循环取到中点m。

    • 如果 a m + 1 ≤ b a^{m+1} \le b am+1b,说明m取小了,l应该右移。
    • 如果 b < a m b < a^m b<am,说明m取大了,r应该左移。
    • 如果 a m ≤ b < a m + 1 a^m\le b < a^{m+1} amb<am+1,说明找到了目标数值。

    该算法的复杂度为 O ( l o g x ⋅ l o g x ⋅ n ) O(logx\cdot logx\cdot n) O(logxlogxn)

    【题解代码】

    解法1:枚举

    • C风格:数组、函数
    #include <bits/stdc++.h>
    using namespace std;
    #define N 2105
    void toNum(char s[], int a[])
    {
        a[0] = strlen(s);
        for(int i = 1; i <= a[0]; ++i)
            a[i] = s[a[0]-i] - '0';
    }
    void numCpy(int a[], int b[])
    {
        for(int i = 0; i <= b[0]; ++i)
            a[i] = b[i];
    }
    void multi(int a[], int b[])//a *= b
    {
        int r[N] = {};
        for(int i = 1; i <= a[0]; ++i)
        {
            int c = 0;
            for(int j = 1; j <= b[0]; ++j)
            {
                r[i+j-1] += c + a[i] * b[j];
                c = r[i+j-1] / 10;
                r[i+j-1] %= 10;      
            }
            r[b[0]+i] += c;
        }
        int ri = a[0] + b[0];
        while(r[ri] == 0 && ri > 1)
            ri--;
        r[0] = ri;
        numCpy(a, r);
    } 
    int numCmp(int a[], int b[])
    {
        if(a[0] > b[0])
            return 1;
        else if(a[0] < b[0])
            return -1;
        else
        {
            for(int i = a[0]; i >= 1; --i)
            {
                if(a[i] > b[i])
                    return 1;
                else if(a[i] < b[i])
                    return -1;
            }
            return 0;
        }
    }
    char s1[N], s2[N];
    int a[N], b[N], l[N], r[N];//l:左边的数 r:右边的数 
    int main()
    {    
        cin >> s1 >> s2;
        toNum(s1, a);
        toNum(s2, b);
        r[0] = 1, r[1] = 1;//r赋值为1     
        for(int x = 0; x <= 20; ++x)
        {
            numCpy(l, r);//l = r
            multi(r, a);//r *= a
            if(numCmp(b, l) >= 0 && numCmp(r , b) > 0)//b >= l && r > b
            {
                cout << x;
                return 0;
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • C++风格:高精度数字类
    #include<bits/stdc++.h>
    using namespace std;
    #define N 2105
    struct HPN
    {
        int a[N];
        HPN()
        {
            memset(a, 0, sizeof(a));
        }
        HPN(string s)
        {
            memset(a, 0, sizeof(a));
            a[0] = s.length();
            for(int i = 1; i <= a[0]; ++i)
                a[i] = s[a[0]-i] - '0';
        }
        int& operator [] (int i)
        {
            return a[i];
        }
        void operator *= (HPN b)//高精乘高精 
        {
            HPN r;
            for(int i = 1; i <= a[0]; ++i)
            {
                int c = 0;
                for(int j = 1; j <= b[0]; ++j)
                {
                    r[i+j-1] += c + a[i] * b[j];
                    c = r[i+j-1] / 10;
                    r[i+j-1] %= 10;      
                }
                r[b[0]+i] += c;
            }
            int ri = a[0] + b[0];
            while(r[ri] == 0 && ri > 1)
                ri--;
            r[0] = ri;
            *this = r;
        }
        int numCmp(int a[], int b[])
        {
            if(a[0] > b[0])
                return 1;
            else if(a[0] < b[0])
                return -1;
            else
            {
                for(int i = a[0]; i >= 1; --i)
                {
                    if(a[i] > b[i])
                        return 1;
                    else if(a[i] < b[i])
                        return -1;
                }
                return 0;
            }
        }
        bool operator >= (HPN b)
        {
            return numCmp(a, b.a) >= 0;
        }
        bool operator > (HPN b)
        {
            return numCmp(a, b.a) > 0;
        }
    };
    int main()
    {
        string s1, s2;
        cin >> s1 >> s2;
        HPN a(s1), b(s2), l, r("1");
        for(int x = 0; x <= 20; ++x)
        {
            l = r;
            r *= a;
            if(b >= l && r > b)
            {
                cout << x;
                return 0;
            } 
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    解法2:二分

    #include<bits/stdc++.h>
    using namespace std;
    #define N 2105
    struct HPN
    {
        int a[N];
        HPN()
        {
            memset(a, 0, sizeof(a));
        }
        HPN(string s)
        {
            memset(a, 0, sizeof(a));
            a[0] = s.length();
            for(int i = 1; i <= a[0]; ++i)
                a[i] = s[a[0]-i] - '0';
        }
        int& operator [] (int i)
        {
            return a[i];
        }
        void setLen(int i)//确定数字位数
        {
            while(a[i] == 0 && i > 1)
                i--;
            a[0] = i;
        }
        HPN operator * (HPN b)//r = a * b
        {
            HPN r;
    	    for(int i = 1; i <= a[0]; ++i)
    	    {
    	        int c = 0;
    	        for(int j = 1; j <= b[0]; ++j)
    	        {
    	            r[i+j-1] += a[i]*b[j] + c;
    	            c = r[i+j-1] / 10;
    	            r[i+j-1] %= 10;
    	        }
    	        r[i+b[0]] += c;
    	    }
    	    r.setLen(a[0] + b[0]);
    		return r;
        }
        HPN operator ^ (int b)//快速幂 求a^b 
        {
        	HPN c = *this, r("1"); 
    		while(b > 0)
    		{
    			if(b % 2 == 1)
    				r = r * c;//高精乘高精 
    			c = c * c;//高精乘高精 
    			b /= 2;
    		}
    		return r;
    	}
        int numCmp(int a[], int b[])
        {
            if(a[0] > b[0])
                return 1;
            else if(a[0] < b[0])
                return -1;
            else
            {
                for(int i = a[0]; i >= 1; --i)
                {
                    if(a[i] > b[i])
                        return 1;
                    else if(a[i] < b[i])
                        return -1;
                }
                return 0;
            }
        }
        bool operator >= (HPN b)
        {
            return numCmp(a, b.a) >= 0;
        }
        bool operator < (HPN b)
        {
            return numCmp(a, b.a) < 0;
        }
    };
    int main()
    {
        string s1, s2;
        cin >> s1 >> s2;
        HPN a(s1), b(s2);
        int l = 0, r = 20, m;
        while(l <= r)
        {
            m = (l + r) / 2;
            if(b >= (a^(m+1)))//注意:^运算符优先级比关系运算符低 
                l = m + 1;
            else if(b < (a^m))
                r = m - 1;
            else
            {
                cout << m;
                return 0;
            }
        } 
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
  • 相关阅读:
    http和https的区别以及常见面试题
    Android开发进阶:Android Framework原理上手与掌控
    算法沉淀——动态规划之子数组、子串系列(上)(leetcode真题剖析)
    技术干货|你需要知道的 10 种常见机器学习算法
    Linux11 --- 进程替换exec系列
    postgresql源码学习(24)—— 事务日志⑤-日志写入WAL Buffer
    网站自动翻译-网站批量自动翻译-网站免费翻译导出
    [附源码]java毕业设计高校社团活动管理系统
    【电力系统】含电热联合系统的微电网运行优化附matlab代码和复现论文
    jvm YGC和FGC发生的具体场景
  • 原文地址:https://blog.csdn.net/lq1990717/article/details/125413370