Yinchuan Regional 2019 I. Base62

Yinchuan Regional 2019
I. Base62
题目链接


I. Base62

题意:

x x x 进制数 z z z 转化为 y y y 进制数。

思路:

很典型的高精。需要先把 x x x 进制转化为 10 10 10 进制,再把 10 10 10 进制转化为 y y y 进制。

x → 10 x\rightarrow10 x10 进制的过程是:设置一个高精度 10 10 10 进制数 t t t 用来暂存,每次先给 t t t 乘以进制 x x x,再取出 x x x 进制数 z z z 当前的最高位,然后加入到 t t t,加一遍就是转化后的数。数学证明如下:假设 z z z 写成 x x x 进制数的形式为 a i a i − 1 … a 1 a 0 a_i a_{i-1}\dots a_1 a_0 aiai1a1a0
t ( 10 进制 ) = z ( x 进制 ) = a i ∗ x i + a i − 1 ∗ x i − 1 + ⋯ + a 1 ∗ x + a 0 ( 10 进制 ) = ( ( … ( ( a i ∗ x + a i − 1 ) ∗ x + a i − 2 ) ∗ x + …   ) ∗ x + a 1 ) ∗ x + a 0 t(10进制)=z(x进制)=a_i*x^i+a_{i-1}*x^{i-1}+\dots+a_1*x+a_0(10进制)\\=((\dots((a_i*x+a_{i-1})*x+a_{i-2})*x+\dots)*x+a_1)*x+a_0 t(10进制)=z(x进制)=aixi+ai1xi1++a1x+a0(10进制)=((((aix+ai1)x+ai2)x+)x+a1)x+a0照着式子递推即可(其实就是秦九韶算法)。这个过程中需要用到高精加法和乘法。

10 → y 10\rightarrow y 10y 进制的过程是:设置一个高精度 y y y 进制数 t t t 用来暂存,然后每次除以 y y y,余数放入 t t t,最后得到的就是 y y y 进制数了。数学证明如下:假设要转化的 10 10 10 进制数写成 y y y 进制数的形式为 a i a i − 1 … a 1 a 0 a_i a_{i-1}\dots a_1 a_0 aiai1a1a0
t ( y 进制 ) = ( ( … ( ( a i ∗ y + a i − 1 ) ∗ y + a i − 2 ) ∗ y + …   ) ∗ y + a 1 ) ∗ y + a 0 ( 10 进制 ) t(y进制)=((\dots((a_i*y+a_{i-1})*y+a_{i-2})*y+\dots)*y+a_1)*y+a_0(10进制) t(y进制)=((((aiy+ai1)y+ai2)y+)y+a1)y+a0(10进制)观察式子,每次除以 x x x 的时候,式子总是 ( …   ) ∗ y + a s (\dots)*y+a_s ()y+as 的形式,余数就是 a s a_s as,我们依次除出来的余数就是 a 0 , a 1 , a 2 , … , a i a_0,a_1,a_2,\dots,a_i a0,a1,a2,,ai。这个过程需要高精除法,同时需要返回余数。

–分割线–

高精算是典型的比较顶级的模拟题目了,需要注意很多东西。这里强调几点:

  1. 一般高精加法和乘法只写高精运算高精,再写个低精转高精的函数就可以不用写高精运算低精的算法了。
  2. 高精数最好从低位开始存储,即小下标存放低位数,方便进位(毕竟没有push_front())。
  3. 高精数实现可以使用vector<int>,能实现动态开空间,也方便维护高精数,以下是一些常用用法(假设定义好了一个高精数叫 a a a):
    1. 返回高精数位数:a.size()
    2. 进位:a.push_back(val)
    3. 去除后导0:while(a.size()>1 && a.back()==0)a.pop_back();(和 reverse(a.begin(),a.end())共同使用可以去除前导0)

code:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int x,y;
string z;
map<char,int> mp1;
map<int,char> mp2;

void print(vector<int> t){
	for(auto it=t.rbegin();it!=t.rend();it++)cout<<mp2[*it];
	puts("");
	return;
}
vector<int> g(int x){
	vector<int> a;
	do{
		a.push_back(x%10);
		x/=10;
	}while(x);
	return a;
}
vector<int> operator+(vector<int> a,vector<int> b){
	int n=max(a.size(),b.size());
	vector<int> c(n,0);
	for(int i=0;i<n;i++)
		c[i]=((i<a.size())?a[i]:0)+((i<b.size())?b[i]:0);
	int ct=0;
	for(int i=0;i<n;i++){
		c[i]+=ct;
		ct=c[i]/10;
		c[i]%=10;
	}
	while(ct){
		c.push_back(ct%10);
		ct/=10;
	}
	return c;
}
vector<int> operator*(vector<int> a,int b){
	for(int i=0;i<a.size();i++)
		a[i]*=b;
	int ct=0;
	for(int i=0;i<a.size();i++){
		a[i]+=ct;
		ct=a[i]/10;
		a[i]%=10;
	}
	while(ct){
		a.push_back(ct%10);
		ct/=10;
	}
	return a;
}
pair<vector<int>,int> operator/(vector<int> a,int b){
	vector<int> c;
	int tmp=0;
	for(int i=a.size()-1;i>=0;i--){
		tmp*=10;
		tmp+=a[i];
		c.push_back(tmp/b);
		tmp%=b;
	}
	reverse(c.begin(),c.end());
	while(c.size()>1 && c.back()==0)c.pop_back();
	return make_pair(c,tmp);
}

vector<int> to10(string s,int p){
	vector<int> t(g(0));
	for(auto x:s){
		t=t*p;
		t=t+g(mp1[x]);
	}
	return t;
}
vector<int> toy(vector<int> t,int y){
	vector<int> a;
	do{
		auto x=t/y;
		t=x.first;
		a.push_back(x.second);
	}while(t!=g(0));
	return a;
}

int main(){
	for(int i=0;i<=9;i++){
		mp1['0'+i]=i;
		mp2[i]='0'+i;
	}
	for(int i=0;i<26;i++){
		mp1['A'+i]=10+i;
		mp2[10+i]='A'+i;
	}
	for(int i=0;i<26;i++){
		mp1['a'+i]=36+i;
		mp2[36+i]='a'+i;
	}
	
	cin>>x>>y>>z;
	
	print(toy(to10(z,x),y));
	
	return 0;
}
  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值