洛谷P1045麦森数(高精度乘法)

题目链接:https://www.luogu.org/problemnew/show/P1045

这题分两问:求位数,求后500位

求位数:公式log10(x)+1,把幂移到前面即可

求后500位:其实如果让求完整的数的话,那就麻烦了,数太多一定时间复杂度高;但现在是只求后500位啊!多的不用管只求这些就行啊,复杂度明显降下来了!求再多次幂,快速幂二分不断分+每次就500位这么小的复杂度,所以一定可以很快完成!

还有个大数乘法技巧就是:不用直接输入时,最好直接用int数组!(省去了char数组转换数字的时间且更方便)

额,又新学了个memcpy复制函数,和for循环一样效果

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <iomanip>
 5 #include <cstdio>
 6 #include <cstring>
 7 #include <cmath>
 8 using namespace std;
 9 typedef long long ll;
10 typedef unsigned long long ull;
11 const int maxn=500;
12 int r[maxn],a[maxn];
13 int c[maxn];
14 int p;
15 
16 void Mul_1()
17 {
18     for(int i=0;i<=maxn-1;i++)
19     {
20         for(int j=0;j<=maxn-1;j++)
21         {
22             if(i+j<=maxn-1)//只算后500位就行!其他不管!不能超越界限,否则报错!
23             {
24                 c[i+j]+=r[i]*a[j];
25                 while(c[i+j]>=10)
26                 {
27                     c[i+j]-=10;
28                     if(i+j+1<=maxn-1) c[i+j+1]+=1;//这里也不能超越界限,否则报错!
29                 }
30             }
31         }
32     }
33 
34     //for(int i=0;i<=maxn-1;i++) r[i]=c[i];
35     memcpy(r,c,sizeof(r));//新学函数hh
36     memset(c,0,sizeof(c));
37 }
38 
39 void Mul_2()//其实2和1一样,只是改了几小处
40 {
41     for(int i=0;i<=maxn-1;i++)
42     {
43         for(int j=0;j<=maxn-1;j++)
44         {
45             if(i+j<=maxn-1)
46             {
47                 c[i+j]+=a[i]*a[j];
48                 while(c[i+j]>=10)
49                 {
50                     c[i+j]-=10;
51                     if(i+j+1<=maxn-1) c[i+j+1]+=1;
52                 }
53             }
54         }
55     }
56 
57     //for(int i=0;i<=maxn-1;i++) a[i]=c[i];
58     memcpy(a,c,sizeof(a));
59     memset(c,0,sizeof(c));
60 }
61 
62 void Qpow(int b)
63 {
64     while(b)
65     {
66         if(b&1) Mul_1();
67         Mul_2();
68         b>>=1;
69     }
70 }
71 
72 int main()
73 {
74     ios::sync_with_stdio(false); cin.tie(0);
75 
76     cin>>p;
77 
78     r[0]=1;
79     a[0]=2;
80     Qpow(p);
81     r[0]-=1;//2的幂不可能0结尾,所以不用考虑借位情况大胆-1即可
82 
83     int answ=p*log10(2)+1;
84     cout<<answ<<endl;
85     for(int i=maxn-1;i>=0;i--)
86     {
87         cout<<r[i];
88         if(i%50==0) cout<<endl;
89     }
90     cout<<endl;
91 
92     return 0;
93 }

完。

原文地址:https://www.cnblogs.com/redblackk/p/9802039.html