高精乘:一位乘多位
——比较简单的高精乘,为多位乘多位做铺垫
T1:国王与麦子
题目描述
传说古代印度有个喜欢下棋的国王叫舍罕,而宰相达依尔是个聪明的大臣,发明了国际象棋。国王玩得爱不惜手,决定奖赏宰相。达依尔说:陛下,我别无他求,请你在这张棋盘的第一个格子里赏我一粒麦子;在第2个格子里赏我2粒麦子;在第3个格子里赏我4粒麦子;在第4个格子里赏我8粒麦子……依此类推直到64个格子,按这张棋盘上各格应赏的麦子全赏给我吧。
国王听了,觉得达依尔的要求并不高,说道:你能如愿以偿的。然而,国王却不知道这个数字是多么巨大啊!
你能帮助国王算算第n个格子的麦子数量吗?
输入
一个正整数n(n<=100)。
输出
一个数,表示第n个格子的麦子数
输入样例 复制
5
输出样例 复制
16
思路
题意很简单读懂,思路也很简单,for循环乘2就行了,主要是考察高精多位乘单位。
代码
#include<iostream>
#include<cstring>
using namespace std;
string ans="1";
int n,x[500],y[500];
int main()
{
cin>>n;
for(int j=2;j<=n;j++)
{
memset(y,0,sizeof(y));
memset(x,0,sizeof(x));
for(int i=0;i<ans.size();i++)
{
x[ans.size()-i]=int(ans[i])-48;
}
int c=ans.size();
for(int i=1;i<=c;i++)
{
y[i]+=x[i]*2;
if(y[i]>=10)
{
y[i+1]++;
y[i]%=10;
}
}
if(y[c+1]!=0)
{
c++;
}
ans="";
for(int i=c;i>=1;i--)
{
ans+=char(y[i]+48);
}
}
cout<<ans;
return 0;
}
总结
第一次用高精乘,觉得有点麻烦,代码比较长。这里高精乘最多进一位,所以不需要很多的处理。
T2:乘积根
题目描述
一个整数的数字乘积根是这样得到的:将此整数中的非零数字相乘,得到的结果再重复上述运算,直到只有一位数为止,此一位数即为原整数的数字乘积根。
例如:整数 99 , 99--> 9*9=81-->8*1=8 , 8 即为 99 的乘积根。
输入
一个n位的整数(n<=255)。
输出
有若干行,每行显示每次数字相乘之后的结果,最后一行只有一个一位数,即为n的乘积根。
输入样例 复制
【输入样例1】
99
【输入样例2】
1203
输出样例 复制
【输出样例1】
81
8
【输出样例2】
6
思路
相对上一题不过是多了拆分和,要注意的是,这里不仅会进一位,会进很多位,要用除和mod来处理。
代码
#include<bits/stdc++.h>
using namespace std;
string a;
string ch(string n)
{
int m[300],q[300],p[300];
string ans1="1";
memset(m,0,sizeof(m));
for(int i=0;i<n.size();i++)
{
m[n.size()-i]=n[i]-48;
}
for(int j=1;j<=n.size();j++)
{
if(m[j]==0) continue;
memset(p,0,sizeof(p));
memset(q,0,sizeof(q));
for(int i=0;i<ans1.size();i++)
{
q[ans1.size()-i]=ans1[i]-48;
}
int c=ans1.size();
for(int i=1;i<=c;i++)
{
p[i]+=m[j]*q[i];
if(p[i]>=10)
{
p[i+1]+=p[i]/10;
p[i]%=10;
}
}
if(p[c+1]!=0)
{
c++;
}
ans1="";
for(int i=c;i>=1;i--)
{
ans1+=char(p[i]+48);
}
}
return ans1;
}
int main()
{
cin>>a;
if(a.size()==1)
{
cout<<a;
return 0;
}
while(a.size()!=1)
{
a=ch(a);
cout<<a<<endl;
}
return 0;
}
总结
也是一道很麻烦的题,注意输入后要特判,不然不会进循环就不会有输出了。
T3:阶乘和
题目描述
已知正整数n(n<=200),请编程计算 1!+2!+…+n! 的值。
注:n!=1 * 2 *… * (n-1) * n。
输入
一个正整数n(n<=200)。
输出
一行,表示阶乘和。
输入样例 复制
4
输出样例 复制
思路
题意很简单,不需要什么思路,就是高精乘和加的结合,特别麻烦。
代码
#include<bits/stdc++.h>
using namespace std;
int a;
string ans="";
string jc(int n)
{
int q[400],p[400];
string ans1="1";
for(int j=1;j<=n;j++)
{
memset(p,0,sizeof(p));
memset(q,0,sizeof(q));
for(int i=0;i<ans1.size();i++)
{
q[ans1.size()-i]=ans1[i]-48;
}
int c=ans1.size();
for(int i=1;i<=c;i++)
{
p[i]+=j*q[i];
if(p[i]>=10)
{
p[i+1]+=p[i]/10;
p[i]%=10;
}
}
if(p[c+1]!=0)
{
while(p[c+1]!=0)
{
c++;
p[c+1]=p[c]/10;
p[c]%=10;
}
}
ans1="";
for(int i=c;i>=1;i--)
{
ans1+=char(p[i]+48);
}
}
return ans1;
}
string jia(string a,string b)
{
int x[500],y[500],z[500];
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(z,0,sizeof(z));
for(int i=0;i<a.size();i++)
{
x[a.size()-i]=int(a[i])-48;
}
for(int i=0;i<b.size();i++)
{
y[b.size()-i]=int(b[i])-48;
}
long long c=max(a.size(),b.size());
for(int i=1;i<=c;i++)
{
z[i]+=x[i]+y[i];
if(z[i]>=10)
{
z[i+1]++;
z[i]%=10;
}
}
while(z[c+1]!=0)
{
c++;
z[c+1]=z[c]/10;
z[c]%=10;
}
string giao;
giao="";
for(int i=c;i>=1;i--)
{
giao+=char(z[i]+48);
}
return giao;
}
int main()
{
cin>>a;
for(int i=1;i<=a;i++)
{
ans=jia(ans,jc(i));
}
cout<<ans;
return 0;
}
总结
麻烦到一种境界,我也是硬敲了八十多行才过得。注意它最后不只会进一位,要用while循环进位。