【题目链接】
ybt 1820:【00NOIP提高组】进制转换
洛谷 P1017 [NOIP2000 提高组] 进制转换
注意:两OJ上题目内容相同,输入输出要求不同
【题目考点】
1. 数制
2. 整除及余数的数学定义
【解题思路】
在题目描述下,对负数r进制数字n,各位为
d
n
d
n
−
1
.
.
.
d
1
d
0
d_nd_{n-1}...d_1d_0
dndn−1...d1d0,按位权展开为:
n
=
d
n
∗
r
n
+
d
n
−
1
∗
r
n
−
1
+
.
.
.
+
d
1
∗
r
1
+
d
0
∗
r
0
n = d_n*r^n+d_{n-1}*r^{n-1}+...+d_1*r^1+d_0*r^0
n=dn∗rn+dn−1∗rn−1+...+d1∗r1+d0∗r0
其中
d
0
,
d
1
,
.
.
.
,
d
n
d_0,d_1,...,d_n
d0,d1,...,dn必须都为正数
除去最后一项,其余项加和一定是r的倍数:
d
n
∗
r
n
+
d
n
−
1
∗
r
n
−
1
+
.
.
.
+
d
1
∗
r
1
=
r
⋅
(
d
n
∗
r
n
−
1
+
d
n
−
1
∗
r
n
−
2
+
.
.
.
+
d
1
∗
r
0
)
d_n*r^n+d_{n-1}*r^{n-1}+...+d_1*r^1 = r\cdot (d_n*r^{n-1}+d_{n-1}*r^{n-2}+...+d_1*r^0)
dn∗rn+dn−1∗rn−1+...+d1∗r1=r⋅(dn∗rn−1+dn−1∗rn−2+...+d1∗r0),简记为
r
⋅
q
r\cdot q
r⋅q
即
n
=
r
⋅
q
+
d
0
n = r\cdot q + d_0
n=r⋅q+d0
其中
0
≤
d
0
<
∣
r
∣
0\le d_0<|r|
0≤d0<∣r∣
d
0
d_0
d0即为数学中n除以r的余数,即n mod r。
其在C++中的写法为(n%r+abs(r))%r
(其原理见:整除及余数相关概念)
而后将
n
/
r
n/r
n/r的商重新赋值给n:
n
=
(
n
−
d
0
)
/
r
n=(n-d_0)/r
n=(n−d0)/r,再用同样的方法求出下一个数位
d
1
d_1
d1。
如此循环,直到n为0。
最后输出记录的各位数字。输出时,注意将10以上的数字转为字母。
【题解代码】
洛谷 P1017 [NOIP2000 提高组] 进制转换
#include<bits/stdc++.h>
using namespace std;
char getCh(int a)
{
return a < 10 ? a+'0' : a-10+'A';
}
int main()
{
string s;
int n, r, a, m;
cin >> n >> r;//r:基数
a = n;
do//用do...while,即便a为0,也会填充到数组中
{
m = (a%r+abs(r))%r;//求 a mod r
s = getCh(m)+s;//将余数接在字符串左边
a = (a-m)/r;
}while(a != 0);
cout << n << '=' << s << "(base" << r << ")";
return 0;
}
ybt 1820:【00NOIP提高组】进制转换
注意处理多组数据,要做状态还原
#include<bits/stdc++.h>
using namespace std;
char getCh(int a)
{
return a < 10 ? a+'0' : a-10+'A';
}
int main()
{
string s;
int n, r, a, m;
while(cin >> n >> r)//r:基数
{
a = n;
s = "";
do//用do...while,即便a为0,也会填充到数组中
{
m = (a%r+abs(r))%r;//求 a mod r
s = getCh(m)+s;//将余数接在字符串左边
a = (a-m)/r;
}while(a != 0);
cout << s << endl;
}
return 0;
}