0
点赞
收藏
分享

微信扫一扫

信息学奥赛一本通 ybt 1820:【00NOIP提高组】进制转换 | 洛谷 P1017 [NOIP2000 提高组] 进制转换

进击的铁雾 2022-01-18 阅读 49
c++NOIP

【题目链接】

ybt 1820:【00NOIP提高组】进制转换
洛谷 P1017 [NOIP2000 提高组] 进制转换
注意:两OJ上题目内容相同,输入输出要求不同

【题目考点】

1.数制

【解题思路】

在题目描述下,对负数r进制数字n,各位为 d n d n − 1 . . . d 1 d 0 d_nd_{n-1}...d_1d_0 dndn1...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=dnrn+dn1rn1+...+d1r1+d0r0
其中 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) dnrn+dn1rn1+...+d1r1=r(dnrn1+dn1rn2+...+d1r0),简记为 r ⋅ q r\cdot q rq
n = r ⋅ q + d 0 ⇒ n − d 0 = r ⋅ q n = r\cdot q + d_0 \Rightarrow n-d_0 = r\cdot q n=rq+d0nd0=rq
其中 0 ≤ d 0 < ∣ r ∣ 0\le d_0<|r| 0d0<r
n需要减一个正数 d 0 d_0 d0,使其是r的整数倍。
d 0 d_0 d0即为r在可能为负数情况下广义的“n对r取模”的值。该值无法在c++中通过n%r得到。
使用该方法求两个整数取模的值,在运算数是正数、负数条件下都适用,写成函数为:

int mod(int a, int b)//求a对b取模的值,在a,b为负数条件下依然适用
{
    for(int r = 0; r < abs(b); ++r)
    {
        if((a-r)%b == 0)
            return r;
    }
}

用该函数求 d 0 d_0 d0的值,记录在数组中。
而后计算 n = ( n − d 0 ) / r n=(n-d_0)/r n=(nd0)/r,再用同样的方法求出下一个数位 d 1 d_1 d1
如此循环,直到n为0。
最后输出记录的各位数字。输出时,注意将10以上的数字转为字母。

【题解代码】

ybt 1820:【00NOIP提高组】进制转换

注意处理多组数据,要做状态还原

#include<bits/stdc++.h>
using namespace std;
int num[50], ni;
int mod(int a, int b)
{
    for(int r = 0; r < abs(b); ++r)
    {
        if((a-r)%b == 0)
            return r;
    }
}
int main()
{
    int n, r, a, m;
    while(cin >> n >> r)//r:基数 
    {
        ni = 0;//状态还原 
        a = n;
        do//用do...while,即便a为0,也会填充到数组中 
        {
            m = mod(a, r);//"取模"结果 
            num[++ni] = m;//将余数填充到数组中 
            a = (a - m) / r; 
        }while(a != 0);
        for(int i = ni; i >= 1; --i)//高位到低位输出数字 
            cout << (num[i] < 10 ? char(num[i]+'0') : char(num[i]-10+'A'));//若超过10,转为16进制输出   
        cout << endl;
    }
    return 0;
}

洛谷 P1017 [NOIP2000 提高组] 进制转换

#include<bits/stdc++.h>
using namespace std;
int num[50], ni;
int mod(int a, int b)
{
    for(int r = 0; r < abs(b); ++r)
    {
        if((a-r)%b == 0)
            return r;
    }
}
int main()
{
    int n, r, a, m;
    cin >> n >> r;//r:基数 
    a = n;
    do//用do...while,即便a为0,也会填充到数组中 
    {
        m = mod(a, r);
        num[++ni] = m;//将余数填充到数组中 
        a = (a - m) / r;    
    }while(a != 0);
    cout << n << '=';
    for(int i = ni; i >= 1; --i)//高位到低位输出数字 
        cout << (num[i] < 10 ? char(num[i]+'0') : char(num[i]-10+'A'));//若超过10,转为16进制输出     
    cout << "(base" << r << ")";
    return 0;
}
举报

相关推荐

0 条评论