信奥赛C++:第一期 进制转换
例1、----------------进制转换------------------------
题目描述
给一个小整数
x
x
x 和一个
x
x
x 进制的数
S
S
S。将
S
S
S 转为
10
10
10 进制数。对于超过十进制的数码,用 A
,B
,
…
\ldots
… 表示。
输入格式
第一行一个整数 x x x;
第二行一个字符串 S S S。
输出格式
输出仅包含一个整数,表示答案。
样例
样例输入
16
7B
样例输出
123
解析:
1.ConvertToDecimal1实现了将一个字符串数字转化为想要得到的十进制数
2.ConvertToDecimal2实现了将一个int型数字转化为想要得到的十进制数
3.ConvertToDecimal3实现了将一个大于十进制数的数字转化为想要得到的十进制数
//将任意一个n进制数转换为10进制
#include <iostream>
using namespace std;
//string与int 相互转换
int StringToInt(string str){
int num = 0;
for (int i = 0; i < str.size(); i++)
{
num = num * 10 + str[i] - '0';//将string的每一位乘位阶累加得到总值
}
return num;
}
void ConvertToDecimal1(int n, int num)//此函数实现了n进制数num转换为十进制数,利用常规思路
{
int decimal = 0;//定义要转换的十进制数
int base = 1;//基础乘阶
while (num > 0)
{
int remainder = num % 10;//n进制数的每一位,从右到左
decimal += remainder * base;//依次乘相应的位阶
base *= n;//位阶每左移一位,base累乘乘阶
num /= 10;//进行下一位的取值
}
cout << decimal << endl;
}
void ConvertToDecimal2(int n, int num){
int ans=0,i=0;
char str[100];
while(num > 0){//将num(int型)每一位存放在str字符数组里
str[i] = num % 10 + '0';//从左到右存放
num /= 10;
i++;
}
for(int j=i-1;j>=0;j--){
ans=ans*n+str[j]-'0';//从右到左累加
}
cout << ans << endl;
}
void ConvertToDecimal3(int n, string num){//此函数实现了高于十进制的类型转换,利用九章算术进行简化操作
//可以转化>10进制
int ans=0;
for(int j=0;j<num.size();j++){
if(num[j]>='0' && num[j]<='9'){//此处做一个是否高于十进制的判断
ans=ans*n+num[j]-'0';
}else{
ans=ans*n+num[j]-'A'+10;//若高于十进制则需要得到此数与A(10)的差值,再经过一个+10运算
}
}
cout << ans << endl;
}
void main_convert(){
int n;
string num;
cin>>n>>num;
if(n>10){
ConvertToDecimal3(n,num);
}
else{
ConvertToDecimal2(n,StringToInt(num));
}
}
int main(){
main_convert();
}
例2、----------------汽车号牌------------------------
题目描述
小 Y 最近发现街上的汽车越来越多了,作为汽车的重要标志——汽车牌照也是越来越不够用了,已经从以前的十进制发展到三十六进制了,以前的一个汽车牌照“苏 D88888”,现在的牌照“苏 D0YY11”。
小 Y 突发其想,想知道他看到的大量汽车牌照中最近的两个汽车牌照相差多少?
输入格式
若干行(不超过 500000 行),每行为一个汽车牌照。
每个汽车牌照为一个 7 位的字符串,格式为 SD×××××,其中一个 × 表示一个 0~9 或A~Z,所涉及的字母均为大写。
输出格式
一行一个数,表示最接近的两个汽车牌照之间的差值,要求为十进制数。
样例
样例输入
SD12345
SD88888
SD22222
SD99999
样例输出
1678245
解析:
首先,将车牌的首字母进行删减,得到5位的36进制数,在对36进制数进行转十进制数,存放再数组中,对数组进行排列,利用哨兵存放间隔最小值,输出即可
#include<bits/stdc++.h>
using namespace std;
int hex36_to_dec(string s) {//车牌号是36进制数,即9个数字+26个字母
s.erase(0, 2);//删除前两位的字母,是对数字进行处理操作
int sum = 0;//定义累加和
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
sum = sum * 36 + s[i] - '0';//数字仅需乘加操作
} else if (s[i] >= 'A' && s[i] <= 'Z') {
sum = sum * 36 + s[i] - 'A' + 10;//字母则需进行求差值操作
}
}
return sum;
}
void main_getDvalue(){
string s;
int i=0;
int a[500000];
while(getline(cin, s)){
if (s.size() == 0)
break;
int num = hex36_to_dec(s);//转化操作
a[i]=num;
i++;
}
sort(a,a+i);//从小到大进行排序
int ans=a[1]-a[0];//利用哨兵,存取最小值
for (int j = 2; j < i; ++j) {
if (a[j]-a[j-1]<ans)
ans=a[j]-a[j-1];//最终得到数组中相差最大的某两个值
}
cout<<ans<<endl;
}
int main(){
main_getDvalue();
}
例3、----------------数列--------------------------
题目描述
给定一个正整数 k,把所有 k 的方幂及所有有限个互不相等的 k 的方幂之和构成一个递增的序列,例如,当 k=3 时,这个序列是:
1,3,4,9,10,12,13,…
该序列实际上就是:30,31,30+31,32,30+32,31+32,30+31+32,…
请你求出这个序列的第 N 项的值(N 用 10 进制数表示,从 1 开始)。
例如,对于 k=3,N=100,正确答案应该是 981。
输入格式
输入文件只有 1 行,为 2 个正整数,用一个空格隔开:k,N。
输出格式
输出文件为计算结果,是一个正整数(在所有的测试数据中,结果均不超过 2.1×109)。(整数前不要有空格和其他符号)。
数据范围
3≤k≤15,
10≤N≤1000
输入样例:
3 100
输出样例:
981
解析:
首先利用转二进制可以发现数列中的序号都可转化为二进制数从1开始排列对应表达式的位阶,利用此种特性,我们可以进行累加操作。
#include<bits/stdc++.h>
using namespace std;
void main_getvalue()
{
int a[100000];
int k,n,i=0;
cin>>k>>n;
while(n){
a[++i]=n%2;
n/=2;
}
int x=1;
int ans=a[1];
for (int j = 2; j <=i ; j++) {
x*=k;
ans+=a[j]*x;
}
cout<<ans<<endl;
}
int main(){
main_getvalue();
}