Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 4050 | Accepted: 1810 |
Description
{ 0-9,A-Z,a-z }
HINT: If you make a sequence of base conversions using the output of one conversion as the input to the next, when you get back to the original base, you should get the original number.
Input
Output
Sample Input
8 62 2 abcdefghiz 10 16 1234567890123456789012345678901234567890 16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2 35 23 333YMHOUE8JPLT7OX6K9FYCQ8A 23 49 946B9AA02MI37E3D3MMJ4G7BL2F05 49 61 1VbDkSIMJL3JjRgAdlUfcaWj 61 5 dl9MDSWqwHjDnToKcsWE1S 5 10 42104444441001414401221302402201233340311104212022133030
Sample Output
62 abcdefghiz 2 11011100000100010111110010010110011111001001100011010010001 10 1234567890123456789012345678901234567890 16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2 16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2 35 333YMHOUE8JPLT7OX6K9FYCQ8A 35 333YMHOUE8JPLT7OX6K9FYCQ8A 23 946B9AA02MI37E3D3MMJ4G7BL2F05 23 946B9AA02MI37E3D3MMJ4G7BL2F05 49 1VbDkSIMJL3JjRgAdlUfcaWj 49 1VbDkSIMJL3JjRgAdlUfcaWj 61 dl9MDSWqwHjDnToKcsWE1S 61 dl9MDSWqwHjDnToKcsWE1S 5 42104444441001414401221302402201233340311104212022133030 5 42104444441001414401221302402201233340311104212022133030 10 1234567890123456789012345678901234567890
先普及一下高精度:
转自:http://blog.csdn.net/devillaw_zhc/article/details/7776578
一.高精度四则运算思想
高精度这个东西其实谁都会,上过小学数学课就知道高精度怎么做了,就是按照人的运算方式,一位一位运算。
1.加法
就是 从个位开始 两个数字相加,如果有进位,就加到十位,再算十位相加,……
2.减法
也是从个位开始 两个数字相减,如果得到的数字小于 0,那么就加上 10,并且把被减数的十位减一,……
3.乘法
第一个数乘以第二个数的个位,写下来,右边与个位对齐,再与第二个数的十位相乘,右边与十位对齐,……
仔细想一想,会发现其实 第一个数 从右数起的第 i 位,不妨设为 2 乘以 第二个数从右数起的第 j 位,不妨设为 8,就相当于 2*10^(i-1) * 8*10^(j-1)
这个乘积所贡献的就是 答案从右数起的 第 i+j-1 位, 即 16 *10^(i+j-2) ,把 1 进位到 从右数起的第 i+j 位上,留下 6 . 即可。
4.除法
除法其实是减法的延伸,打个比方,24723 除以 123 。
按照人的做法,从高位开始一位一位取出被除数的数字
先是 2,判断是否小于 123, 小于那答案这一位就置 0
再取一位,24, 还是小于,答案这一位置0
再取一位,247,这时候比 123 大了,那就看能减多少个 123, 发现减 2 次之后比 123 小了,那么答案的第 3 位上就是2, 减剩下的数是 1
重复那个过程,取一位,12, 小于 123 ,答案这一位置 0
再取一位, 123, 不小于 123 了, 看能减多少个, 发现能减一个, 那么答案第 5 位就是 1
剩下的数为 0 , 而被除数的数也被取光了,运算结束。
答案为 00201 ,整理一下即为 201。
二、存储方式
实践下来为了方便起见,把最低位存在数组的第一位,最高位存在最后一位,是最容易编写程序的,道理很简单,因为每次都是从最低位开始做的,而且乘法显然会方便很多。
我一般用一个 struct 来表示一个高精度数,里面有个 a 数组, a[0] 为该数的长度,a[1] 是个位,a[2] 是十位,以此类推。
三.压位高精度
本质其实是一样的,只不过存储方式与输出方式有不同。
比如数 103
用十位的高精度存 a[0] = 3, a[1] = 3, a[2] = 0, a[3] = 1
用百位的高精度存 a[0] = 2, a[1] = 3, a[2] = 1
要注意的是输出的时候 a[1] 不能只输出一个 3, 而要输出 03.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int power = 1; //每次运算的位数为10的power次方,在这里定义为了方便程序实现
const int base = 10; //10的power次方。
//要压位的时候,只需改power 和 base即可,如压万位高精,那么power = 4, base = 10000
const int MAXL = 1001; //数组的长度。
char a[MAXL], b[MAXL];
struct num
{
int a[MAXL];
num() { memset(a, 0, sizeof(a)); } //初始化
num(char *s) //将一个字符串初始化为高精度数
{
memset(a, 0, sizeof(a));
int len = strlen(s);
a[0] = (len+power-1) / power; //数的长度
for (int i=0, t=0, w; i < len ;w *= 10, ++i)
{
if (i % power == 0) { w = 1, ++t; }
a[t] += w * (s[i]-'0');
}
//初始化数组,这里自己模拟一下,应该很容易懂的~
}
void add(int k) { if (k || a[0]) a[ ++a[0] ] = k; } //在末尾添加一个数,除法的时候要用到
void re() { reverse(a+1, a+a[0]+1); } //把数反过来,除法的时候要用到
void print() //打印此高精度数
{
printf("%d", a[ a[0] ]);
//先打印最高位,为了压位 或者 该高精度数为0 考虑
for (int i = a[0]-1;i > 0;--i)
printf("%0*d", power, a[i]);
//这里"%0*d", power的意思是,必须输出power位,不够则前面用0补足
printf("\n");
}
} p,q,ans;
bool operator < (const num &p, const num &q) //判断小于关系,除法的时候有用
{
if (p.a[0] < q.a[0]) return true;
if (p.a[0] > q.a[0]) return false;
for (int i = p.a[0];i > 0;--i)
{
if (p.a[i] != q.a[i]) return p.a[i] < q.a[i];
}
return false;
}
num operator + (const num &p, const num &q) //加法,不用多说了吧,模拟一遍,很容易懂
{
num c;
c.a[0] = max(p.a[0], q.a[0]);
for (int i = 1;i <= c.a[0];++i)
{
c.a[i] += p.a[i] + q.a[i];
c.a[i+1] += c.a[i] / base;
c.a[i] %= base;
}
if (c.a[ c.a[0]+1 ]) ++c.a[0];
return c;
}
num operator - (const num &p, const num &q) //减法,也不用多说,模拟一遍,很容易懂
{
num c = p;
for (int i = 1;i <= c.a[0];++i)
{
c.a[i] -= q.a[i];
if (c.a[i] < 0) { c.a[i] += base; --c.a[i+1]; }
}
while (c.a[0] > 0 && !c.a[ c.a[0] ]) --c.a[0];
//我的习惯是如果该数为0,那么他的长度也是0,方便比较大小和在末尾添加数时的判断。
return c;
}
num operator * (const num &p, const num &q)
//乘法,还是模拟一遍。。其实高精度就是模拟人工四则运算!
{
num c;
c.a[0] = p.a[0]+q.a[0]-1;
for (int i = 1;i <= p.a[0];++i)
for (int j = 1;j <= q.a[0];++j)
{
c.a[i+j-1] += p.a[i]*q.a[j];
c.a[i+j] += c.a[i+j-1] / base;
c.a[i+j-1] %= base;
}
if (c.a[ c.a[0]+1 ]) ++c.a[0];
return c;
}
num operator / (const num &p, const num &q) //除法,这里我稍微讲解一下
{
num x, y;
for (int i = p.a[0];i >= 1;--i) //从最高位开始取数
{
y.add(p.a[i]); //把数添到末尾(最低位),这时候是高位在前,低位在后
y.re(); //把数反过来,变为统一的存储方式:低位在前,高位在后
while ( !(y < q) ) //大于等于除数的时候,如果小于的话,其实答案上的该位就是初始的“0”
y = y - q, ++x.a[i]; //看能减几个除数,减几次,答案上该位就加几次。
y.re(); //将数反过来,为下一次添数做准备
}
x.a[0] = p.a[0];
while (x.a[0] > 0 && !x.a[x.a[0]]) --x.a[0];
return x;
}
int main()
{
scanf("%s", a);
scanf("%s", b);
reverse(a, a+strlen(a));
reverse(b, b+strlen(b));
p = num(a), q = num(b);
ans = p + q;
ans.print();
ans = p - q;
ans.print();
ans = p * q;
ans.print();
ans = p / q;
ans.print();
}
ac代码
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 1005;
char str[MAXN];
int ans[MAXN],res[MAXN],start[MAXN];
int oldBase,newBase;
int getNum(char c){
if(c>='0'&&c<='9') return c-'0';
if(c>='A'&&c<='Z') return c-'A'+10;
return c-'a'+36;
}
char getChar(int c){
if(c>=0&&c<=9) return c+'0';
if(c>=10&&c<=35)return c-10+'A';
return c-36+'a';
}
void change(){
start[0]=strlen(str);
for(int i=1; i<=start[0]; i++)
start[i]=getNum(str[i-1]);
}
void solve(){
int i,j,y;
memset(res,0,sizeof(res));
while(start[0]>=1){
i=1;y=0;
ans[0]=start[0];
while(start[0]>=i){
y=y*oldBase+start[i];
ans[i++]=y/newBase;
y%=newBase;
}
res[++res[0]]=y;
i=1;
while(i<=ans[0]&&ans[i]==0) i++;
memset(start,0,sizeof(ans));
for(j=i; j<=ans[0]; j++) start[++start[0]]=ans[j];
memset(ans,0,sizeof(ans));
}
}
void print(){
cout<<oldBase<<" "<<str<<endl<<newBase<<" ";
for(int i=res[0]; i>=1; i--) cout<<getChar(res[i]);
cout<<endl<<endl;
}
int main()
{
int t;
cin>>t;
while(t--){
cin>>oldBase>>newBase>>str;
change();
solve();
print();
}
return 0;
}
某大牛写的,佩服
#include <stdio.h>
#include <string.h>
const int maxn = 1000;
int t[maxn], A[maxn];
char str1[maxn], str2[maxn];
int n, m;
void solve()
{
int i, len, k;
len = strlen(str1);
for(i=len; i>=0; --i) t[len-1-i] = str1[i] -(str1[i]<58 ? 48: str1[i]<97 ? 55: 61);
for(k=0; len;) {
for(i=len; i>=1; --i) {
t[i-1] +=t[i]%m*n;
t[i] /= m;
}
A[k++] = t[0] % m;
t[0] /=m;
while(len>0&&!t[len-1]) len--;
}
str2[k] =NULL;
for(i=0; i<k; i++)
str2[k-1-i] = A[i]+(A[i]<10 ? 48: A[i]<36 ? 55:61);
}
int main()
{
int T;
scanf("%d",&T);
while(T--) {
scanf("%d%d%s",&n, &m, str1);
solve();
printf("%d %s\n%d %s\n\n", n, str1, m, str2);
}
return 0;
}