对于高精度乘法和加法的同学可以学学这几个题
高精度乘法
高精度加法
文章目录
题意

给出一个整数和一个浮点数,求2的整数次幂和这个浮点数相乘的结果最后四舍五入。、
分析
我们可以发现,n的范围是1000,2的1000次方非常大,我们用pow只能求到2的31次方左右,即便我们开了long long也是远远不够的,所以我们显然可以知道,这题肯定是用高精度来写的。
不过如果在比赛的时候没有时间敲高精度(确实很费时间),我们直接暴力跑他这个小范围拿个部分分算了。👇下面给大家看看正解和部分解
部分解

直接用上最简单的方法,round函数求四舍五入,pow求2的n次幂。然后直接就暴力写了。下面看一下这个代码。
cpp
void Solve () {
int n;double x;
cin>>n>>x;
int t = pow(2,n);
long double pos = round(t*x);
cout<<pos;
return ;
}
这个方法显然不是很好,但是简单。下面看下正解(我的写法,不知道是不是正解,但是过题就是正解)
全解

对于2的n次幂我们可以求n次高精度,每一次和2相乘,这个时间复杂度我们是可以接受的。
对于浮点数,我们可以直接忽略小数点,在二者相乘完之后我们在往后加小数点,最后根据小数点的位置我们再四舍五入判断再加一,不过这个加一我们不能简单的加一,我们要用高精度。
不过我想了一下发现好像遍历着相加好像更简单。
难点部分就是在于高精乘,如果有模板的话,直接复制粘贴一会就写完了,不过没有的话,我们就只能自己手撸了。好难撸。
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
#define ALL(x) x.begin(),x.end()
#define PII pair<int,int>
#define pb push_back
int a[12000],b[12000],c[12000];
string gaojin (string s,string y) {//高精乘模板
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
for (int j=s.size()-1,i = 0;j>=0;j--,i++)
a[i]=s[j]-'0';
for (int i=0,j=y.size()-1;j>=0;i++,j--)
b[i]=y[j]-'0';
for (int i=0;i<y.size();i++)
{
for (int j=0;j<s.size();j++)
c[i+j]+=a[j]*b[i];
}
int f=s.size()+y.size();
for (int i=0;i<f;i++)
{
if (c[i]>=10)
{
c[i+1]+=c[i]/10;
c[i]%=10;
}
}
while (c[f]==0&&f>0)
f--;
string ans="";
for (int i=f;i>=0;i--) ans.insert(ans.end(),c[i]+'0');
return ans;
}
string gaojinjia (string s1,string s2) {//高精加模板
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
for (int i=s1.size()-1,j=0;i>=0;i--,j++) a[j] = s1[i]-'0';
for (int i=s2.size()-1,j=0;i>=0;i--,j++) b[j] = s2[i]-'0';
int k = max(s1.size(),s2.size());
for (int i=0;i<k;i++) {
c[i] += a[i]+b[i];
if (c[i]>=10) {
c[i+1] += c[i]/10;
c[i]%=10;
}
}
string ans;
if (c[k]!=0) k++;
for (int i=k-1;i>=0;i--) ans.insert(ans.end(),c[i]+'0');
return ans;
}
void Solve () {
int n;string s;//直接读入string形s,方便高精操作
cin>>n>>s;
string t = "1";
while (n--) t = gaojin(t,"2");//不断用高精乘2求2的n次幂
int w = s.find('.');
string s1 = s.substr(0,w);
string s2 = s.substr(w+1);
string S = s1+s2;//将小数点去掉,但是用erase的时候不知道哪里错了,就用简单的加减了
w = s.size()-w-1;//求出小数点在哪里
string T = gaojin(S,t);//T是乘完之后的数,包括整数和小数,不过小数点没有明确
char ch = T[T.size()-w];//找到小数点的位置后一位的数字
string ans1 = T.substr(0,T.size()-w);//将整数部分提取出来
if (ch>='5') cout<<gaojinjia(ans1,"1");//如果小数点后一位大于5,就高精+1
else cout<<ans1;
return ;
}
signed main () {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int _ = 1;
// cin >> _ ;
while (_--) Solve (); return 0;
}
⚠️注意初始化!!!注意数组范围!!!
由于我总是忘记初始化,所以总是被卡很长时间,写的比较丑陋,对不起。
后言
这题是真的难写,难度到不是很大,就是一个模拟题,不过码量是真不少。写了一下又帮助自己回忆了一下高精度的知识。多加练习,不然容易生疏。