信息学奥赛一本通 1820:【00NOIP提高组】进制转换 | 洛谷 P1017 [NOIP2000 提高组] 进制转换
【題目鏈接】
ybt 1820:【00NOIP提高組】進制轉換
洛谷 P1017 [NOIP2000 提高組] 進制轉換
注意:兩OJ上題目內容相同,輸入輸出要求不同
【題目考點】
1.數制
【解題思路】
在題目描述下,對負數r進制數字n,各位為dndn?1...d1d0d_nd_{n-1}...d_1d_0dn?dn?1?...d1?d0?,按位權展開為:
n=dn?rn+dn?1?rn?1+...+d1?r1+d0?r0n = d_n*r^n+d_{n-1}*r^{n-1}+...+d_1*r^1+d_0*r^0n=dn??rn+dn?1??rn?1+...+d1??r1+d0??r0
其中d0,d1,...,dnd_0,d_1,...,d_nd0?,d1?,...,dn?必須都為正數
除去最后一項,其余項加和一定是r的倍數:
dn?rn+dn?1?rn?1+...+d1?r1=r?(dn?rn?1+dn?1?rn?2+...+d1?r0)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?qr\cdot qr?q
即n=r?q+d0?n?d0=r?qn = r\cdot q + d_0 \Rightarrow n-d_0 = r\cdot qn=r?q+d0??n?d0?=r?q
其中0≤d0<∣r∣0\le d_0<|r|0≤d0?<∣r∣
n需要減一個非負數d0d_0d0?,使其是r的整數倍。
d0d_0d0?即為r在可能為負數情況下廣義的“n對r取?!钡闹?。該值無法在c++中通過n%r得到。
方法1:
枚舉從0到|r|-1的所有值,看哪一個滿足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;} }方法2:
先求n/r=xn / r = xn/r=x,那么有:n=r?x+mn = r*x + mn=r?x+m,此時一定有∣m∣<∣r∣|m|<|r|∣m∣<∣r∣
m的值可能是正的也可能是負的。
根據上文結論:n需要減一個非負數,使其是r的整數倍。,所以必須讓m≥0m\ge0m≥0
如果m<0m<0m<0,則公式化為:n=r?(x+1)+m?rn = r*(x+1)+m-rn=r?(x+1)+m?r。
m?rm-rm?r一定是非負數。
根據該原理,mod函數可以設計為:可以直接求商,再求余數,如果余數是負數,那么再減一個除數,使其變為非負數。
以上兩種mod函數求兩個整數取模的值,在運算數是正數、負數條件下都適用。
用mod函數求d0d_0d0?的值,記錄在數組中。
而后計算n=(n?d0)/rn=(n-d_0)/rn=(n?d0?)/r,再用同樣的方法求出下一個數位d1d_1d1?。
如此循環,直到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; }使用第二種mod函數寫法:
#include<bits/stdc++.h> using namespace std; int num[50], ni; int mod(int a, int b) {int x = a / b, m;m = a - x*b;if(m < 0)m = m - b;return m; } int main() {int n, r, a, m;cin >> n >> r;//r:基數 cout << n << '=';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 << "(base" << r << ")";return 0; }總結
以上是生活随笔為你收集整理的信息学奥赛一本通 1820:【00NOIP提高组】进制转换 | 洛谷 P1017 [NOIP2000 提高组] 进制转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: go 查看全局安装了哪些包_如何用 GV
- 下一篇: 信息学奥赛一本通 1413:确定进制 |