本题链接:蓝桥杯2024年第十五届省赛真题-R 格式 - C语言网
题目:
样例:
|--------|
| 2 3.14 |
[输入]
|----|
| 13 |
[输出]
思路:
根据题意,结合数据范围,这是一道模板的高精度乘以低精度问题。
题意是double 类型 d 与 2 的n 次幂相乘,最后四舍五入。
我们换一下视角,看作 对于double 类型 d ,与 n 个 2 相乘,最后四舍五入。
这样就很快解出答案了,就是对于double小数部分需要微调一下即可。
高精度乘法模板函数如下:
cpp
// 高精度乘以低精度 模板
inline string mul(string A,int x)
{
vector<int>a; // 取出每一位
int len = A.size(); // 倒着取每一位,方便低位到高位的计算
for(int i = len - 1;~i;--i) a.emplace_back(A[i] - '0');
vector<int>tem; // 存储计算结果
int t = 0; // 存储临时进位数
for(int i = 0;i < len;++i)
{
int num = t + a[i] * x; // 开始每一位相乘
tem.emplace_back(num % 10); // 取计算结果个位
t = num / 10; // 计算进位
}
while(t > 0)
{
// 如果最后有高位的进位,我们进位
tem.emplace_back(t % 10);
t /= 10;
}
string ans = ""; // 存储最后计算结果
// 将结果转回为 string ,并返回结果
int temlen = tem.size();
for(int i = temlen - 1;~i;--i) ans += char(tem[i] + '0');
return ans;
}
高精度加法模板函数如下:
cpp
// 高精度加法模板
inline string ADD(string A,string B)
{
vector<int>a,b;
int alen = A.size();
int blen = B.size();// 倒着取每一位,方便低位到高位的计算
for(int i = alen - 1;~i;--i) a.emplace_back(A[i] - '0');
for(int i = blen - 1;~i;--i) b.emplace_back(B[i] - '0');
vector<int>tem; // 存储计算结果
int t = 0; // 存储临时进位数
for(int i = 0;i < alen or i < blen;++i)
{
int num = t; // 开始每一位相加
if(i < alen) num += a[i];
if(i < blen) num += b[i];
tem.emplace_back(num % 10);// 取计算结果个位
t = num / 10;// 计算进位
}
while(t > 0)
{
// 如果最后有高位的进位,我们进位
tem.emplace_back(t % 10);
t /= 10;
}
string ans = ""; // 存储最后计算结果
// 将结果转回为 string ,并返回结果
int temlen = tem.size();
for(int i = temlen - 1;~i;--i) ans += char(tem[i] + '0');
return ans;
}
代码详解如下:
cpp
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define int long long
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;
inline void solve();
signed main()
{
// freopen("a.txt", "r", stdin);
// IOS;
int _t = 1;
// cin >> _t;
while (_t--)
{
solve();
}
return 0;
}
// 高精度乘以低精度 模板
inline string mul(string A,int x)
{
vector<int>a; // 取出每一位
int len = A.size(); // 倒着取每一位,方便低位到高位的计算
for(int i = len - 1;~i;--i) a.emplace_back(A[i] - '0');
vector<int>tem; // 存储计算结果
int t = 0; // 存储临时进位数
for(int i = 0;i < len;++i)
{
int num = t + a[i] * x; // 开始每一位相乘
tem.emplace_back(num % 10); // 取计算结果个位
t = num / 10; // 计算进位
}
while(t > 0)
{
// 如果最后有高位的进位,我们进位
tem.emplace_back(t % 10);
t /= 10;
}
string ans = ""; // 存储最后计算结果
// 将结果转回为 string ,并返回结果
int temlen = tem.size();
for(int i = temlen - 1;~i;--i) ans += char(tem[i] + '0');
return ans;
}
// 高精度加法模板
inline string ADD(string A,string B)
{
vector<int>a,b;
int alen = A.size();
int blen = B.size();// 倒着取每一位,方便低位到高位的计算
for(int i = alen - 1;~i;--i) a.emplace_back(A[i] - '0');
for(int i = blen - 1;~i;--i) b.emplace_back(B[i] - '0');
vector<int>tem; // 存储计算结果
int t = 0; // 存储临时进位数
for(int i = 0;i < alen or i < blen;++i)
{
int num = t; // 开始每一位相加
if(i < alen) num += a[i];
if(i < blen) num += b[i];
tem.emplace_back(num % 10);// 取计算结果个位
t = num / 10;// 计算进位
}
while(t > 0)
{
// 如果最后有高位的进位,我们进位
tem.emplace_back(t % 10);
t /= 10;
}
string ans = ""; // 存储最后计算结果
// 将结果转回为 string ,并返回结果
int temlen = tem.size();
for(int i = temlen - 1;~i;--i) ans += char(tem[i] + '0');
return ans;
}
inline void solve()
{
int n;
string d;
bool vis = false; // 检查是否符合四舍五入
cin >> n >> d;
// 如果 d 是整数的情况
if((int)d.find(".") == -1)
{
while(n--)
{
d = mul(d,2);
}
}else
{
int pos = d.find("."); // 找到 小数点 . 的位置下标
int len = d.size() - pos - 1; // 计算小数部分长度
d.erase(d.begin() + pos); // 删掉 小数点 .
// 将 d 所有的数字当作整数相乘计算
while(n--)
{
d = mul(d,2);
}
pos = d.size() - len; // 更新小数点位置
// 查看小数点后一位是否符合四舍五入
if((d[pos] - '0') >= 5) vis = true;
// 删掉小数部分,保留整数
while(len--) d.erase(d.begin() + d.size() - 1);
if(vis) d = ADD(d,"1"); // 如果符合四舍五入,那么进一
}
cout << d << endl;
}