目录
6、例题(2)来喽—数制转换—(以10为媒介,y总眼中的小学数奥)
1、16进制和8进制的前的“0x”,“0”知识点
- 八进制数是一种逢八进一的计数体制,基数是8,用0~7表示,如077。
- 八进制数以数字0开头。
- 十六进制数是一种逢十六进一的计数体制,基数是16,用0~9,A~F表示,如0xFF或0XFF。
- 十六进制数以数字0和字母x的组合0x或0X开头。其中字母x是不区分大小写的,即0x与0X等价。
- 但是对于八进制的输出是字母o,而不是数字0。
#include<iostream> #include<cstring> #include<algorithm> using namespace std; int a=11; int main() { printf("%o %d %x",a,a,a);//依次将11转换成8进制,10进制,16进制打印出 return 0; }
2、strtol函数
- strtol作用:将一个任意(1-36)进制数转化为10进制数,传入字符串,返回是long int型。
函数为strtol(char *nptr, char *endptr, int base);
base是被转化的数的进制,非法字符会赋值给endptr,nptr是要转化的字符
对于nptr指向的字符串,其开头和结尾处的空格被忽视,字符串中间的空格被视为非法字符。
#include<iostream> #include<cstring> #include<algorithm> using namespace std; int main() { char buffer[20]="1000"; char *stop; printf("%d",strtol(buffer, &stop, 2));//输出结果为8 // cout<<strtol(buffer, &stop, 2); return 0; }
- 若出现非法字符,则该非法字符后面的所有字符都赋给endptr(stop)。
#include<iostream> #include<cstring> #include<algorithm> using namespace std; int main() { char buffer[20]="1000211";//"2"为非法字符 char *stop; printf("%d",strtol(buffer, &stop, 2));//仍然输出8 return 0; }
3、itoa函数
- itoa作用:将一个10进制的数转化为n进制的值、其返回值为char型。
- itoa(num, str, x);num是一个要转化的10进制数,str是转化结果,x为目标进制。
#include<iostream> #include<algorithm> #include<cstring> #include<stdio.h> using namespace std; int main() { int num = 10; char str[100]; printf("%s\n", itoa(num, str, 2));//输出结果为1010 return 0; }
4、进制转化输入、输出简便用法
hex,Hexadecimal .十六进制。
dec,Decimal ,十进制。
oct,Octal ,八进制。#include<iostream> #include<cstring> #include<algorithm> using namespace std; int a, b, c; int main() { cin >> hex >> a; printf("%x\n", a);//16进制输入,16进制输出 cout << dec << a << endl;//16进制输入,10进制输出 cin >> dec >> b; printf("%d\n", b);//10进制输入,10进制输出 cout << dec << b << endl;//10进制输入,10进制输出 cin >> oct >> c; printf("%o\n", c);//8进制输如,8进制输出 cout << dec << c << endl;//8进制输入,10进制输出 return 0; }
5、例题(1)来喽——22蓝桥杯E题
题目描述
进制规定了数字在数位上逢几进一。 X 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某 种 X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X 进制数 321 转换为十进制数为 65。 现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确 定,只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进 制。请你算出 A − B 的结果最小可能是多少。 请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数 字要小于其进制。
输入格式
第一行一个正整数 N,含义如题面所述。 第二行一个正整数 Ma,表示 X 进制数 A 的位数。 第三行 Ma 个用空格分开的整数,表示 X 进制数 A 按从高位到低位顺序各 个数位上的数字在十进制下的表示。 第四行一个正整数 Mb,表示 X 进制数 B 的位数。 第五行 Mb 个用空格分开的整数,表示 X 进制数 B 按从高位到低位顺序各 个数位上的数字在十进制下的表示。 请注意,输入中的所有数字都是十进制的。
对于 30% 的数据,N ≤ 10; Ma, Mb ≤ 8.
对于 100% 的数据,2 ≤ N ≤ 1000; 1 ≤ Ma, Mb ≤ 100000; A ≥ B.输出格式
输出一行一个整数,表示 X 进制数 A − B 的结果的最小可能值转换为十进 制后再模 1000000007 的结果。
输入样例
11 3 10 4 0 3 1 2 0
输出样例
94
样例说明
当进制为:最低位2进制,第二数位5进制,第三数位11进制时,减法得到的差最小。此时A在十进制下是108,B在十进制下是14,差值是94。
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int N = 1e6 + 10;
const int M = 1000000007;
int n, m, x, a[N], b[N], c[N];
long long int sum;
int main()
{
cin >> x >> n;
for (int i = n; i >= 1; i--) cin >> a[i];
cin >> m;
for (int i = m; i >= 1; i--) cin >> b[i];
int ma = max(n, m);
for (int i = ma; i >= 1; i--)
{
int maa = max(a[i] + 1, b[i] + 1);
if (maa > x) maa = x;
if (maa < 2) maa = 2;
c[i] = maa;
}
for (int i = ma; i >= 2; i--)//最后一项不能加进去c[0]=0
{
sum = ((sum + a[i] - b[i] + M) * c[i - 1]) % M;
}
sum = (sum + a[1] - b[1]) % M;//最后一项单独计算
cout << sum << endl;
return 0;
}
5.1、进制转换思维导图
手工制图,不够更详细,还望各位见谅;
5.2、进制转换思想
-
首先理解题意真的很重要!很重要!看懂了才有思路!!
-
和正常的进制转换相比,此题的转换在于不同数位上的进制数不同,而且取决于该数位的大小(进制位是该数位最大数加1,且末位最低为2进制);
-
要注意相同位数时第一组数减第二组数得到值为负数(例如321&&431中的‘2’减‘3’==‘-1’)(我分享两种方法1.不需要考虑负数2.需要考虑负数);
-
还要考虑两组数是否有相同的位数(可能存在a为321而b为21这种情况);
-
关于为什么是乘下一位进制c[i-1],我举一个例子比如说十进制的12(因为只有当个位满了之后才会向十位进一,所以等于1*10+2*1==12);
-
本题也属于一道贪心题;
5.3、主旨展现
-
用a数组逆序存第一组数,用b数组逆序存第二组数;(逆序存的目的是为了排除位数不相同的情况)
-
用c数组存储该位上的进制数;(注意末尾最低也是2进制)
-
因为可能数值太大,注意运算时要%1000000007;
6、例题(2)来喽—数制转换—(以10为媒介,y总眼中的小学数奥)
题目描述
求任意两个不同进制非负整数的转换(2 进制 ∼ 16 进制),所给整数在 int 范围内。
不同进制的表示符号为(0,1,…,9,a,b,…,f)或者(0,1,…,9,A,B…,F)
输入格式
输入只有一行,包含三个整数 a,n,b。a 表示其后的 n 是 a 进制整数,b 表示欲将 a 进制整数 n 转换成 b 进制整数。a,b 是十进制整数。
数据可能存在包含前导零的情况。
输出格式
输出包含一行,该行有一个整数为转换后的 b 进制数。输出时字母符号全部用大写表示,即(0,1,…,9,A,B,…,F)。
数据范围
2≤a,b≤16,
给定的 a 进制整数 n 在十进制下的取值范围是 [1,2147483647]。输入样例:
15 Aab3 7
输出样例:
210306
#include<iostream>//进制转换
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long LL;
string shu = "0123456789ABCDEF";
LL a, b, sum;
string s, str = "";
int main()
{
cin >> a >> s >> b;
LL l = s.size();
for (int i = 0; i < s.size(); i++)
{
if (s[i] >= '0' && s[i] <= '9')
{
sum += (s[i] - '0') * pow(a, l - i - 1);
}
else if (s[i] >= 'a' && s[i] <= 'f')
{
sum += (s[i] - 'a' + 10) * pow(a, l - i - 1);
}
else if (s[i] >= 'A' && s[i] <= 'F')
{
sum += (s[i] - 'A' + 10) * pow(a, l - i - 1);
}
}
//cout << sum << endl;
while (sum)
{
int x = sum % b;
str += shu[x];
sum = sum / b;
}
reverse(str.begin(),str.end());
cout << str << endl;
return 0;
}
7、例题(3)来喽——数的进制转换——(一道高精度好题)
题目描述
编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。
这里有 62 个不同数位 {0−9,A−Z,a−z}。
输入格式
第一行输入一个整数,代表接下来的行数。接下来每一行都包含三个数字,首先是输入进制(十进制表示),然后是输出进制(十进制表示),最后是用输入进制表示的输入数字,数字之间用空格隔开。
输入进制和输出进制都在 2 到 62 的范围之内。
(在十进制下)A=10,B=11,…,Z=35,a=36,b=37,…,z=61 (0−9 仍然表示 0−9)。
输出格式
对于每一组进制转换,程序的输出都由三行构成。第一行包含两个数字,首先是输入进制(十进制表示),然后是用输入进制表示的输入数字。
第二行包含两个数字,首先是输出进制(十进制表示),然后是用输出进制表示的输入数字。
第三行为空白行。
同一行内数字用空格隔开。
输入样例:
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
输出样例:
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
#include<iostream>//先将n进制转换为10进制,再讲10进制转换为m进制
#include<algorithm>//由于中间结果可能很大,需要用到高精度运算
#include<string>
using namespace std;
const int N = 1e6 + 10;
int m, x, y, a[N];
string st, s;
int main()
{
cin >> m;
while (m--)
{
s = "", st = "";
cin >> x >> y >> st;
int j = 1;
for (int i = st.size() - 1; i >= 0; i--)//先将其转化成相对应的十进制数字
{
if (st[i] >= '0' && st[i] <= '9') a[j++] = st[i] - '0';
else if (st[i] >= 'A' && st[i] <= 'Z') a[j++] = st[i] - 'A' + 10;
else if (st[i] >= 'a' && st[i] <= 'z') a[j++] = st[i] - 'a' + 36;
}
int ma = st.size();
while (ma)/核心代码
{
int c = 0;
for (int i = ma; i >= 1; i--)
{
int b = (c * x + a[i]) / y;
c = (c * x + a[i]) % y;
a[i] = b;
}
while (a[ma] == 0 && ma >= 1) ma--;
if (c >= 0 && c <= 9) s += char(c + '0');//老是写成(c-'0')
else if (c >= 10 && c <= 35) s += char(c + 'A' - 10);//老是写成(c-'A'+10)
else if (c >= 36 && c <= 61) s += char(c + 'a' - 36);//老是写成(c-'a'+36)
}
reverse(s.begin(), s.end());//反转函数
cout << x << " " << st << endl;
cout << y << " " << s << endl;
cout << endl;
}
return 0;
}