信息学奥赛一本通 1925:【03NOIP普及组】麦森数 | OpenJudge NOI 4.4 1708:麦森数 | 洛谷 P1045 [NOIP2003 普及组] 麦森数
【題目鏈接】
ybt 1925:【03NOIP普及組】麥森數(shù)
OpenJudge NOI 4.4 1708:麥森數(shù)
洛谷 P1045 [NOIP2003 普及組] 麥森數(shù)
【題目考點(diǎn)】
1. 高精度
2. 求一個(gè)數(shù)字位數(shù)
設(shè)正整數(shù)x的的位數(shù)為n,那么有:n=?lgx?+1n = \lfloor lgx \rfloor + 1n=?lgx?+1(lgxlgxlgx:以10為底x的對(duì)數(shù))
證明:正整數(shù)x和它的位數(shù)n之間滿足:n=?lgx?+1n = \lfloor lgx \rfloor + 1n=?lgx?+1
已知:10n?1≤x<10n10^{n-1}\le x <10^n10n?1≤x<10n(舉例:10≤15<100,100≤168<100010\le 15<100, 100\le168<100010≤15<100,100≤168<1000)
對(duì)不等式各邊取以10為底的對(duì)數(shù),有:n?1≤lgx<nn-1\le lgx < nn?1≤lgx<n
所以有:n?1=?lgx?n-1 = \lfloor lgx \rfloorn?1=?lgx?
所以:n=?lgx?+1n = \lfloor lgx \rfloor + 1n=?lgx?+1
【解題思路】
- 求2p?12^p-12p?1的位數(shù)
x-1的位數(shù)與x的位數(shù)只有在x為10n10^n10n(n為正整數(shù))的情況下才不同,其它情況下一定相同。
2p2^p2p一定不是10n10^n10n,所以2p?12^p-12p?1的位數(shù)和2p2^p2p的位數(shù)相同。
根據(jù)公式n=?lgx?+1n = \lfloor lgx \rfloor + 1n=?lgx?+1,求出2p2^p2p的位數(shù)為:
n=?lg2p?+1=?p?lg2?+1n = \lfloor lg2^p \rfloor + 1=\lfloor p\cdot lg2 \rfloor + 1n=?lg2p?+1=?p?lg2?+1 - 求2p?12^p-12p?1的后500位
當(dāng)p>1時(shí)2p2^p2p的個(gè)位只可能是2,4,6或8,所以2p2^p2p與2p?12^p-12p?1只是個(gè)位不同。可以先求出2p2^p2p的后500位的數(shù)字,然后個(gè)位再減1即為結(jié)果。
要求出2p2^p2p的后500位的數(shù)字,需要使用高精度計(jì)算。高精度數(shù)字只設(shè)為500位,如果向更高位進(jìn)位,則忽略(因?yàn)楦呶坏臄?shù)值無(wú)法影響最低的500位)。
求2p2^p2p的后500位有兩種方法:
解法1:每次乘以2x2^x2x
p的最大值達(dá)到大約3?1063*10^63?106,每次進(jìn)行500位的運(yùn)算,乘以500后,約為1.5?1091.5*10^91.5?109,一定會(huì)超時(shí)的。
如果每次乘2,需要乘m次;那么如果每次乘4,只需要乘m/2次,每次乘8,只需要乘m/3次…每次乘2x2^x2x,共需要乘m/x次m/x次m/x次
如果x取20,那么需要乘3?106/20=1.5?1053*10^6/20=1.5*10^53?106/20=1.5?105,再乘以500,總運(yùn)算次數(shù)為7.5?1077.5*10^77.5?107,不會(huì)超時(shí)了。
先做p%x次乘2,再做p/x次乘2x2^x2x,即可求出2p2^p2p,使用高精乘低精。
解法2:快速冪
快速冪中要求解的數(shù)字和基數(shù)都達(dá)到高精度,所以要寫高精乘高精。
快速冪進(jìn)行中,要對(duì)數(shù)字或基數(shù)模500,因?yàn)橹挥袛?shù)字或基數(shù)的末500位影響結(jié)果的末500位。
【題解代碼】
解法1:每次乘以2x2^x2x
#include <bits/stdc++.h> using namespace std; #define N 1005 #define M 500 void MultiAndMod(int a[], int b)// a=a*b取末M位 高精乘低精 {int c = 0, i;//進(jìn)位 for(i = 1; i <= a[0]; ++i){a[i] = a[i] * b + c;c = a[i] / 10;a[i] %= 10;}while(c > 0){a[i] = c % 10;c /= 10;i++;}while(a[i] == 0 && i > 1)i--;a[0] = i;if(a[0] > M)//限制高精度數(shù)字a的位數(shù),忽略高于500的數(shù)字忽a[0] = M; } int main() {int p, a[N] = {}, r, m;//a:數(shù)字?jǐn)?shù)組 r:剩下需要乘以2的次數(shù) cin >> p;cout << floor(p * log10(2)) + 1 << endl;//求位數(shù)a[0] = a[1] = 1;//將a設(shè)為1m = p / 20;//m:a乘以2^20的次數(shù)r = p % 20;//r:a乘以2的次數(shù) for(int i = 1; i <= r; ++i)MultiAndMod(a, 2);for(int i = 1; i <= m; ++i)MultiAndMod(a, 1048576);//1048576:是2^20 a[1]--;//減1 for(int i = 500; i >= 50; i -= 50)//i:起始位數(shù) {for(int j = i; j > i-50; --j)cout << a[j];cout << endl;} return 0; }解法2:快速冪
#include <bits/stdc++.h> using namespace std; #define N 1005 #define M 500 void MultAndMod(int a[], int b[])//高精乘高精 a = a*b%M {int r[N] = {}, ri;for(int i = 1; i <= a[0]; ++i){int c = 0;//進(jìn)位 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;}ri = a[0] + b[0];while(r[ri] == 0 && ri > 1)ri--;r[0] = ri;if(r[0] > M)//只取末500位r[0] = M;for(int i = 0; i <= r[0]; ++i)//結(jié)果r賦值給aa[i] = r[i]; } int main() {int p, a[N] = {1,1}, b[N] = {1,2};//a,b是數(shù)字?jǐn)?shù)組。a:結(jié)果,初值為1 b:基數(shù),初值為2 cin >> p;//指數(shù)cout << floor(p * log10(2)) + 1 << endl;//求位數(shù)while(p > 0)//快速冪{if(p % 2 == 1)MultAndMod(a, b);//a = a*b%MMultAndMod(b, b);//b = b*b%Mp /= 2; }a[1]--;//減1 for(int i = 500; i >= 50; i -= 50)//輸出解 i:起始位數(shù) {for(int j = i; j > i-50; --j)//輸出50個(gè)數(shù) cout << a[j];cout << endl;} return 0; }總結(jié)
以上是生活随笔為你收集整理的信息学奥赛一本通 1925:【03NOIP普及组】麦森数 | OpenJudge NOI 4.4 1708:麦森数 | 洛谷 P1045 [NOIP2003 普及组] 麦森数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 信息学奥赛一本通 2042:【例5.10
- 下一篇: linux查看删除init内容,linu