解题思路:
作为比赛的第二道大题 这个还是有点难度的,数据量这么大 就是明摆考察高精度了。2^1000 大概是10的300次方 10e300*10e1024 位数在两千位以内 所以不用考虑内存不够。
这里给出两种解法 一个是使用数组 一个是使用队列。使用数组需要多考虑一下n的边界。
因为有小数的情况,所以需要记录一下小数点的位置(或者说是小数占几位),无论怎么乘小数位是不会变的,因为每次*2 所以整数位最多上进1位。
详见代码:
#include <bits/stdc++.h> using namespace std; int A[10010],B = 2; int n=0; void mul(int A[]) { int t=0; // 用于存储进位 for(int i=0; i<n; i++) { A[i]=(A[i]*B) + t; t=A[i]/10; A[i]%=10; } // 如果有进位 if(t!=0) { A[n]=t; n++; } } int main() { int N; scanf("%d",&N); // 输入需要乘以的次数 string s; cin>>s; // 输入浮点数 int flag=0; for(int i=s.size()-1; i>=0; i--) { if(s[i]=='.') { flag=s.size()-1-i; // 记录小数点的位置 continue; } else { A[n]=(s[i]-'0'); n++; } } while(N--) { mul(A); // 执行乘法操作 } // 注意 此时为倒序储存 3.14为413 所以起始位i=n-1 十分位为 flag-1(数组有下标0) // 判断是否需要四舍五入 if(A[flag-1]>=5) { int t=1; // 末尾+1 注意i=flag for(int i=flag; i<n; i++) { A[i]=A[i]+t; t=A[i]/10; A[i]%=10; } if(t!=0) { A[n]=t; n++; } } // 直接打印 for(int i=n-1; i>=flag; i--) { cout<<A[i]; } return 0; }
解法二:
使用stl库里面的队列 有队列就不用考虑n的位置问题 不过不能像数组一样直接获得十位数判断四舍五入。
#include <bits/stdc++.h> using namespace std; // 用于模拟大整数的乘法,每次乘以2 void mul(vector<int> &ver) { int t=0; // 用于存储进位 for(auto &x:ver) { x=x*2+t; // 当前位乘以2并加上之前的进位 t=x/10; // 计算新的进位 x=x%10; // 更新当前位的值 } if(t) ver.push_back(t); // 如果还有进位,则添加到vector的末尾 } int main() { int n; scanf("%d",&n); // 输入需要乘以的次数 string s; cin>>s; // 输入浮点数 reverse(s.begin(),s.end()); // 反转字符串,这样小数的处理会变得更简单 vector<int> ver; // 存储每一位的整数值 int flag=0; for(int i=0; i<s.size(); i++) { if(s[i]=='.') { flag=i; // 记录小数点的位置 continue; } else { ver.push_back(s[i]-'0'); // 将字符转换为数字并添加到vector中 } } while(n--) { mul(ver); // 执行乘法操作 } reverse(ver.begin(),ver.end()); // 再次反转,恢复原始顺序 int bak=-1; while(flag--) { bak=ver.back(); // 从小数点开始,逐个移除位 ver.pop_back(); } // 如果最后一位(被移除的小数部分的最后一位)大于等于5,则进行四舍五入 if(bak>=5) { reverse(ver.begin(),ver.end()); int flag=1; for(int i=0; i<ver.size(); i++) { ver[i]+=flag; flag=ver[i]/10; ver[i]=ver[i]%10; } if(flag) { ver.push_back(flag); } reverse(ver.begin(),ver.end()); } for(auto x:ver) { printf("%d",x); // 输出结果 } return 0; }
ps:再写一个骗分的代码 就是使用double无视位数问题,double最大可达10的三百多次方 和一千位比起来小了点 但是应该可以过50%的测试点(此代码无法通过全部测试点!!) 不过能得一分是一分。
#include <bits/stdc++.h> using namespace std; int main() { int n; double d; cin>>n>>d; d = round(pow(2,n)*d); printf("%.0lf\n",d); return 0; }
0.0分
177 人评分
2003年秋浙江省计算机等级考试二级C 编程题(2) (C语言代码)浏览:561 |
C语言程序设计教程(第三版)课后习题5.7 (C语言代码)浏览:591 |
用筛法求之N内的素数。 (C语言代码)浏览:890 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:701 |
A+B for Input-Output Practice (IV) (C语言代码)浏览:513 |
Tom数 (C语言代码)浏览:517 |
交换Easy (C语言代码)浏览:805 |
链表数据求和操作 (C语言代码)浏览:1035 |
简单的a+b (C语言代码)浏览:857 |
生日日数 (C语言代码)浏览:1574 |