【蹄鉄コレクション】第23週 キャリーシステムの話題

10進法に関するトピック






MT2186バイナリ? 違う!

難易度:ゴールド制限時間:1秒メモリ使用量:128M
トピックの説明

小馬兄弟は数字に非常に敏感で、似たような数字をたくさん与えられたとしても、これまでに出現したことのない数字を見つけることができます。
少し退屈かもしれません。Xiaoma 兄弟は、nnを含む文字列配列 nums を提供します。n 個のバイナリ文字列 (すべて長さnnn )、今度は配列にないバイナリ文字列を見つけるように求められます。複数の解がある場合は、最小の小数に対応する解を返します。

フォーマット

入力形式: スペースで区切られたバイナリ文字列配列の行;
出力形式: 配列にないバイナリ文字列。

サンプル1

入力: 01 10

出力: 00

述べる

其中: 1 ≤ n ≤ 16 1 \le n \le 16 1n図16において、nums内のすべての文字は互いに異なっている。


関連する知識ポイント:进位制


答え


この質問では、入力データにまだ現れていない最小値 (すべてのデータの最小値は 0) を見つける必要があります。ただし、タイトルで指定されたデータはバイナリ文字列 (正当な) なので、表示されない最小の数値を見つけるには、すべての入力バイナリ文字列を 10 進数に変換し、これらの数値をセット nums に格納する必要があります。次に、0 から順に整数を逆方向に列挙し、設定した数値にない数値があれば、その数値は入力データにまだ出現していない最小の数値であることを意味します。注: この数値の形式も変換する必要があります。つまり、数値は 10 進数から 2 進数の文字列に変換されます (長さは入力データの長さと一致する必要があります)。

この問題を解決するための完全なコードを以下に直接示します (すでに AC です)。

/*
    MT2186 二进制?不同! 
    测试数据:001 100 000  
*/
#include<bits/stdc++.h> 
using namespace std;

set<int> nums;

// 该函数将(合法的)二进制数字串转换为十进制数字 
int getDecFromBin(string str)
{
    
    
    int sum = 0, base = 1;
    for(int i=str.size()-1; i>=0; i--){
    
    
        sum += base*(str[i]-'0');
        base *= 2;
    }
    return sum;
} 

// 将一个十进制数转换为指定长度的二进制字符串
string toBinary(int n, int len)
{
    
    
    string str = "";
    while(len--){
    
    
        if(n&1) str = "1"+str;
        else str = "0"+str;
        n >>= 1;
    }
    return str;
} 

int main( )
{
    
    
    // 输入数据
    string str;
    while(cin>>str)
        nums.insert(getDecFromBin(str));
    // 记录当前输入二进制字符串的长度
    int binStrlen = str.length();
    // 寻找最小值,并在进行格式转换后输出 
    for(int i=0; ; i++){
    
    
    	// 找到一个尚未在集合中出现的最小数值
        if(nums.find(i) == nums.end()){
    
    
            cout<<toBinary(i, binStrlen)<<endl;
            break;
        }
    }
    return 0;
}



MT2187エクセルのトラブル

難易度:ダイヤモンド制限時間:2秒メモリ使用量:128M
トピックの説明

Excel を使用したことがありますか?
Excel では、最初の列は A、2 列目は B、というようにラベルが付けられ、26 列目は Z になります。これに 2 文字の列番号が続きます: 列 27 は AA、列 28 は AB ... ZZ というラベルの付いた列の後に 3 文字の列番号が続きます。
行番号は 1 から始まる整数です。
セルの座標は列番号と行番号で連結されます。たとえば、BC23 は列 55、行 23 のセルを表します。
RXCY と呼ばれる座標系も使用される場合があります。X と Y は整数であり、座標 (X, Y) は対応するセルの位置を直接表します。たとえば、R23C55 は前述のセルです。
Xiaoma 兄弟、指定されたセル座標を次の形式の別の座標系に変換するプログラムを書いてください。

フォーマット

入力形式: 最初の行の整数 T (1≤T≤10^5) は、T 回の問い合わせがあることを示し、
     次の T 行にはそれぞれ座標が含まれます。
出力形式: 出力 T 行、1 行につき 1 つの変換された座標。

サンプル1

入力: 3
   R12C3
   AE32
   BB11

出力: C12
   R32C31
   R11C54

述べる

どの座標も正しいです。入力データと出力データが int の範囲内にあることを確認してください。入力データと出力データの文字はすべて大文字です。


関連する知識ポイント: 进位制


答え


この問題は表面的には 2 つの座標形式の変換を行っていますが、実際には塩基の変換も調べています。たとえば、Excel 形式の座標の場合、その列番号 BC は 10 進数の 55 に相当します ( 2 × 2 6 1 + 3 × 2 6 0 = 55 2×26^1+3×26^0=55)2×2 61+3×2 60=55 )、したがって、質問では、BC23 は行 55、列 23 のセルとして解析されます。したがって、ここでの基数変換の問題は実際には 10 進数であり、A − Z AZZで表される 2 つの 16 進数の間で変換します。

この質問では、入力データがどのような座標表現形式であるかを指定していないため、まず座標形式を特定する必要があります。2 つの座標形式を観察すると、Excel 形式の座標は「文字 + 数字」であるのに対し、RXCY 形式の座標は「文字 + 数字 + 文字 + 数字」であることがわかります。 RXCY の形式では数字の後ろに文字が表示されますが、Excel 形式では数字の後ろに文字が表示されません。したがって、この本質的な違いに基づいてフォーマット認識を実行し、その後のフォーマット変換を実行できます。

入力座標列の形式検出が完了したら、それぞれ形式変換を行うことができます。具体的な変換プロセスは難しくありません (詳細については、この後のサンプル質問を参照してください: MT2189 3 進コンピューター 1、MT2190 3 進コンピューター 2)。この問題を解決するための完全なコードは以下に直接示されています (AC)。

/*
	MT2187 excel的烦恼 
*/
#include<bits/stdc++.h> 
using namespace std;

string str;
int T;
char apt[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// 检测当前的坐标字符串属于那种格式:
// 0 EXCEL 格式 
// 1 RXCY  格式
bool getFormat(string str)
{
    
    
	bool flag = 0;
	int strlen = str.length();
	for(int i=0; i<strlen; i++) {
    
    
		// 数字出现标记 
		if(isdigit(str[i]))
			flag = true;
		// 检测是否为 RXCY 模式
		if(flag && str[i]=='C')
			return true;
	}
	return false;
} 

// 格式转换 
void transform(string str)
{
    
    
	// 格式识别
	bool mode =  getFormat(str);
	// 格式转换 
	int row = 0, col = 0, len = str.length();
	if(mode){
    
     // mode 1:RXCY 转 ECXCEL 格式 
		// 定位 R 与 C 所在位置 
		int R = str.find("R"), C = str.find("C");
		// 取出行号和列号 
		for(int i=R+1; i<C; i++) 
			row = row*10+str[i]-'0';
		for(int i=C+1; i<len; i++)
			col = col*10+str[i]-'0';
		// 将十进制数转换为以 A-Z 表达的二十六进制数 
		int tmp;
		string ans;
		while(col > 0){
    
    
			tmp = col%26;
			if(tmp == 0){
    
    
				tmp = 26;
				col -= 26;
			}
			ans += apt[tmp];
			col /= 26;
		} 
		reverse(ans.begin(), ans.end());
		// 格式化输出 
		cout<<ans<<row<<endl;
	}else{
    
    	// mode 0:ECXCEL 转 RXCY 格式 
		// 将二十六进制数转换为十进制数 
		for(int i=0; i<len; i++)
			if(!isdigit(str[i]))
				col = col*26+str[i]-'A'+1;
			else
				row = row*10+str[i]-'0';
		// 格式化输出 
		cout<<"R"<<row<<"C"<<col<<endl;
	}
}

int main( )
{
    
    
	// 输入数据
	cin>>T;
	for(int i=1; i<=T; i++){
    
    
		cin>>str;
		// 将当前的坐标表达式转换为另一种格式 
		transform(str);
	}
    return 0;
}


MT2188 シングルコンディションと

難易度:ゴールド制限時間:1秒メモリ使用量:128M
トピックの説明

「単一条件」は、数理論理学で一般的に使用される 5 つの接続詞の 1 つであり、「→」で示されます。それは二項演算です。これは、「if...then....」、「 because...so...」、「as long as...then...」などと同等です。「含意」とも呼ばれます。「p→q」は「p なら q」と読み、p を前件、q を後件と呼びます。

その真理値表は次のとおりです。

単一条件の真理値表

たとえば、「排他的または和」はa 1 ⨁ a 2 ⨁ … ⨁ an a_1⨁a_2⨁…⨁a_nです。ある1ある2ある、「単一の条件付き合計」、つまりa 1 → a 2 → ⋯ → a_1→a_2→⋯→a_n が必要になります。ある1ある2ある,对 a 1 , a 2 , … , a n a_1,a_2,…,a_n ある1ある2ある単一の条件演算の合計をビット単位で実行します。
unsigned int型として動作してください。

フォーマット

入力形式: 1 行目に整数nnn は、 nnがあることを意味します単一の条件付き合計を必要とするn 個の整数。2 行目にnn
     を入力します単一の条件付き合計を必要とするn 個の整数。
出力形式: unsigned int 整数を出力します。

サンプル1

入力: 10
   1 2 3 4 5 6 7 8 9 10

出力: 4294967290

述べる

データの 100% の場合: 1 ≤ n ≤ 5e 6 1≤n ≤ 5e61n5e6 _ _


関連する知識ポイント:位运算


答え


タイトルにある真理値表を観察することは、見つけるのは難しくありません。「p→q」は、実際には、ビット演算「~p|q」(p または q ではありません) を実行するのと同じです。これを理解したら、次のコードを直接記述できます。

/*
	MT2188 单条件和 
	用 scanf 接受输入才能得满分 
*/
#include<bits/stdc++.h> 
using namespace std;

int main( )
{
    
    
	// 输入数据
	int n;
	unsigned ans, tmp;
	cin>>n>>ans;
	// 执行运算
	for(int i=1; i<n; i++) {
    
    
		scanf("%u",&tmp);
		ans = ~ans | tmp;
	}
	// 输出 
	cout<<ans<<endl; 
    return 0;
}


MT2189 トライナリコンピュータ 1

難易度:ゴールド制限時間:1秒メモリ使用量:128M
トピックの説明

3進法コンピュータは、3進法に基づいて開発されたコンピュータです。フォトニックコンピュータ研究の分野にも携わっています。
3 値コードの特徴の 1 つは対称性、つまり反対の数の一貫性であるため、2 値コードとは異なり、符号なし数の概念がありません。このようにして、ターナリ コンピュータのアーキテクチャははるかに単純で、より安定し、より経済的になります。コマンド セットも読みやすく、非常に効率的です。
一般に、命題は必ずしも真か偽であるとは限らず、未知の場合もあります。三値論理では、記号 1 は真を表し、記号 -1 は偽を表し、記号 0 は未知を表します。この論理式は、人工知能におけるコンピューターの開発傾向により一致しており、コンピューターにファジー操作と自律学習の可能性を提供します。
この問題では、入力された対称 3 進数を対応する 10 進数に変換してください。対称 3 進数は 0/1/2 では表現されず、1/0/-1 で表現されるため、対称と呼ばれています。この問題では、-1 は記号 - で表されますが、1 と 0 は直接表すことができます。

フォーマット

入力形式: 最初に整数nnを入力しますnはデータセットの数を示し、
     次のnnn行の場合、各行は対称 3 進整数に入ります。
出力形式: 2 ~ n+1 行目に入力された対称 3 進整数ごとに、それぞれ 10 進数形式で出力します。

サンプル1

入力: 8
   -0
   -1
   -
   0
   1
   1-
   10
   1–

出力: -3
   -2
   -1
   0
   1
   2
   3
   5

述べる

この例では、2 = 3 − 1 、 3 = 3 + 0 × 1 、 5 = 9 − 3 − 1 2=3-1、 3=3+0 \times 1、 5=9-3-12=31、3 _ _=3+0×1、5 _ _=931 .
データの 100% の場合:1 ≤ n ≤ 1 e 6 1 ≤ n ≤ 1e61n1 e 6 の場合、入力対称 3 進数に対応する整数は int 型の範囲内にあります


関連する知識ポイント:平衡三进制


答え


この質問では実際に基数変換、つまり平衡 3 進数から 10 進数への変換を調べます。

まず第一に、どんなkk であってもそれを知る必要があります。k進数 (集合A k = a 1 a 2 ⋯ an A_k=a_1 a_2⋯a_n=ある1ある2ある) 10 進数への変換はすべて次の式に従います。

n = ∑ i = 1 naikn − in=\sum_{i=1}^na_i k^{ni}n=i = 1ある私はkn i

其中, a i a_i ある私はkkを意味しますk進数はiiiビットのフェッチ番号nnn はその長さを表します。

たとえば、2 進数 1010 を 10 進数に変換すると、次のようになります。

n = a 1 k 4 − 1 + a 2 k 4 − 2 + a 3 k 4 − 3 + a 4 k 4 − 4 = 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 0 × 2 0 = 10 n=a_1 k^{4-1}+a_2 k^{4-2}+a_3 k^{4-3}+a_4 k^{4-4}=1×2^3+0×2^2 +1×2^1+0×2^0=10n=ある1k4 1+ある2k4 2+ある3k4 3+ある4k4 4=1×23+0×22+1×21+0×20=10

16 進数 AE86 を 10 進数に変換すると、次のようになります。

n = a 1 k 4 − 1 + a 2 k 4 − 2 + a 3 k 4 − 3 + a 4 k 4 − 4 = 10 × 1 6 3 + 14 × 1 6 2 + 8 × 1 6 1 + 6 × 1 6 0 = 44678 n=a_1 k^{4-1}+a_2 k^{4-2}+a_3 k^{4-3}+a_4 k^{4-4}=10×16^3+14 ×16^2+8×16^1+6×16^0=44678n=ある1k4 1+ある2k4 2+ある3k4 3+ある4k4 4=10×1 63+14×1 62+8×1 61+6×1 60=44678

同様に、3 進数もこの式を満たします。ただし、この問題は非常に特殊です。平衡 3 進数の 2 は -1 で表されますが、これは一般公式で与えられる計算方法には影響しません。たとえば、タイトルに示されている平衡 3 進数の場合1--、変換プロセスは次のようになります。

n = a 1 k 3 − 1 + a 2 k 3 − 2 + a 3 k 3 − 3 = 1 × 3 2 + ( − 1 ) × 3 1 + ( − 1 ) × 3 0 = 9 − 3 − 1 = 5 n=a_1 k^{3-1}+a_2 k^{3-2}+a_3 k^{3-3}=1×3^2+(-1)×3^1+(-1)× 3^0=9-3-1=5n=ある1k3 1+ある2k3 2+ある3k3 3=1×32+( 1 )×31+( 1 )×30=931=5

この考え方によれば、この問題を解決するための完全なコードは次のように記述できます。

以下は、上記のアイデアに基づいて記述された完全なコードです (すでに AC です)。

/*
    MT2189 三进制计算机1  
    输出转换结果时不能用 endl ,否则会超时 
*/
#include<bits/stdc++.h> 
using namespace std;

const int N = 105;
int w[N], n, ans, len;
char s[N];

int main( )
{
    
    
    // 取消cin与stdin的同步(加速文件读取速度) 
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
    // 输入数据
    cin>>n; 
    
    // 构建乘位 
    w[0] = 1;
    for(int i=1; i<=100; i++)
        w[i] = w[i-1]*3;
            
    // 进制转换与输出 
    while(n--){
    
    
        cin>>s;
        ans = 0;
        len = strlen(s);
        // 进制转换 
        for(int i=len-1; i>=0; i--){
    
    
            if(s[i] == '1') ans += w[len-1-i];
            if(s[i] == '-') ans -= w[len-1-i];
        }
        // 输出转换结果
        cout<<ans<<"\n";
    }
    return 0;
}

さらに、この質問には特に注意が必要な点が 2 つあります。

  1. ファイルの読み取りを高速化するには、cin と stdin の間の同期をキャンセルする必要があります。キャンセルしないとタイムアウトになります (原理については、「C++ の入力と出力に関するいくつかの問題」を参照してください)。
  2. 改行を出力するときは、「endl」の代わりに「\n」を使用する必要があります。そうしないとタイムアウトになります。

もちろん、C メソッドを使用してデータの入出力を行うこともできるため (つまり、cin と cout を scanf と printf で置き換える)、上記の問題を心配する必要はありません。



MT2190 トライナリコンピュータ2

難易度:ダイヤモンド制限時間:1秒メモリ使用量:128M
トピックの説明

3進法コンピュータは、3進法に基づいて開発されたコンピュータです。フォトニックコンピュータ研究の分野にも携わっています。
3 値コードの特徴の 1 つは対称性、つまり反対の数の一貫性であるため、2 値コードとは異なり、符号なし数の概念がありません。このようにして、ターナリ コンピュータのアーキテクチャははるかに単純で、より安定し、より経済的になります。コマンド セットも読みやすく、非常に効率的です。
一般に、命題は必ずしも真か偽であるとは限らず、未知の場合もあります。三値論理では、記号 1 は真を表し、記号 -1 は偽を表し、記号 0 は未知を表します。この論理式は、人工知能におけるコンピューターの開発傾向により一致しており、コンピューターにファジー操作と自律学習の可能性を提供します。
この問題では、入力された対称 3 進数を対応する 10 進数に変換してください。対称 3 進数は 0/1/2 では表現されず、1/0/-1 で表現されるため、対称と呼ばれています。この問題では、-1 は記号 - で表されますが、1 と 0 は直接表すことができます。

フォーマット

入力形式: 最初に整数nnを入力しますnはデータセットの数を示し、
     次のnnn行の場合、各行には 10 進整数が入力されます。
出力形式: 行 2~n+1 に入力された 10 進整数ごとに、その対称 3 進形式をそれぞれ出力します。

サンプル1

入力: 8
   -3
   -2
   -1
   0
   1
   2
   3
   5

出力: -3
   -0
   -1
   -
   0
   1
   1-
   10
   1–

述べる

この例では、2 = 3 − 1 、 3 = 3 + 0 × 1 、 5 = 9 − 3 − 1 2=3-1、 3=3+0 \times 1、 5=9-3-12=31、3 _ _=3+0×1、5 _ _=931 .
データの 100% の場合:1 ≤ n ≤ 1 e 6 1 ≤ n ≤ 1e61n1 e 6 の場合、入力対称 3 進数に対応する整数は int 型の範囲内にあります


関連する知識ポイント:平衡三进制


答え


この質問は、前の質問の要件のまったく逆です。つまり、入力された各 10 進数を対称な 3 進数に変換して出力することが求められます。
まず第一に、任意の 10 進数nn が存在することを知る必要があります。nをkk変換しますkaryシステムは次のプロセスに従います。

  1. 現在のビット値は次のとおりです: n%k;
  2. 数値を逆方向にフェッチし続ける (つまり、より高い桁を取得する) には、数値n = nkn=\frac{n}{k}を更新します。n=k
  3. n = 0 の場合、変換は終了します。

たとえば、10 進数の 10 を 2 進数に変換するプロセスは次のとおりです。

  • 1桁目:n % 2 = 10 % 2 = 0 n\%2 = 10\%2 = 0n %2=10%2=0、更新n = n 2 = 10 2 = 5 n=\frac{n}{2}=\frac{10}{2}=5n=2=210=5
  • 2 桁目: n % 2 = 5 % 2 = 1 n\%2 = 5\%2 = 1n %2=5%2=1、更新n = n 2 = 5 2 = 2 n=\frac{n}{2}=\frac{5}{2}=2n=2=25=2
  • ビット 3: n % 2 = 2 % 2 = 0 n\%2 = 2\%2 = 0n %2=2%2=0、更新n = n 2 = 2 2 = 1 n=\frac{n}{2}=\frac{2}{2}=1n=2=22=1
  • ビット 4: n % 2 = 1 % 2 = 1 n\%2 = 1\%2 = 1n %2=1%2=1、更新n = n 2 = 1 2 = 0 n=\frac{n}{2}=\frac{1}{2}=0n=2=21=0、変換は終了します。

したがって、10 進数の 10 に対応する 2 進数は 1010 になります。

同様に、10 進数から 3 進数への変換もこのアルゴリズムに従います。たとえば、10 進数 11 から 3 進数への変換は次のようになります。

  • 1桁目:n % 3 = 11 % 3 = 2 n\%3 = 11\%3 = 2n %3=11%3=2、更新n = n 3 = 11 3 = 3 n=\frac{n}{3}=\frac{11}{3}=3n=3=311=3
  • ビット 2: n % 3 = 3 % 3 = 0 n\%3 = 3\%3 = 0n %3=3%3=0、更新n = n 3 = 3 3 = 1 n=\frac{n}{3}=\frac{3}{3}=1n=3=33=1
  • ビット 3: n % 3 = 1 % 3 = 1 n\%3 = 1\%3 = 1n %3=1%3=1、更新n = n 3 = 1 3 = 0 n=\frac{n}{3}=\frac{1}{3}=0n=3=31=0、変換は終了します。

したがって、10 進数の 11 に対応する 3 進数は 102 になります。

この問題で変換が必要な「平衡三元系」では、「2」をすべて「-1」に置き換える必要があります。この置換は、実際には、指定されたビットの値を 1 減らすことに相当します (この数値の全体的な観点から、実際には1 × kp 1×k^pだけ減らされます)1×kp )、この数値の全体的な値が変更されないようにするには、前のビットからビットを借用する、つまり、このビットの前の値に 1 を追加する必要があります。たとえば、10 進数の 11 から得られる 3 進数は 102 で、その数値の下位ビットから上位ビットに向かってスキャンします。まず、最後に「2」があるため、この数値は「-」に置き換えられます。 "、上位ビット " 0" が "1" に置き換えられます (つまり、 が取得されます11-)。その後、逆方向にスキャンを続け、シーケンス全体の数値が正当であることがわかり、10 進数から変換された平衡 3 進数が得られます。 11が得られる11-以下のことを確認できます。

n = a 1 k 3 − 1 + a 2 k 3 − 2 + a 3 k 3 − 3 = 1 × 3 2 + 1 × 3 1 + ( − 1 ) × 3 0 = 9 + 3 − 1 = 11 n= a_1 k^{3-1}+a_2 k^{3-2}+a_3 k^{3-3}=1×3^2+1×3^1+(-1)×3^0=9+ 3-1=11n=ある1k3 1+ある2k3 2+ある3k3 3=1×32+1×31+( 1 )×30=9+31=11

3 進数 122 の場合を考えてみましょう。最後の「2」を借用すると、真ん中の「2」が数字の「3」になります、つまりこの時点では、真ん中の「13-3」はこの基数での最大値に達しているので、キャリーされているので、この時点の数値は になります20-; 上位ビットまでスキャンを続け、最上位ビットが「2」であることが判明するため、「-」に変換する必要があり、上位ビットから借用する必要があります。ついに入手しました1-0-以下を確認できます。

122 : n = 1 × 3 2 + 2 × 3 1 + 2 × 3 0 = 9 + 6 + 2 = 17 122:n=1×3^2+2×3^1+2×3^0=9+ 6+2=17122 n=1×32+2×31+2×30=9+6+2=17
1 − 0 − : n = 1 × 3 3 + ( − 1 ) × 3 2 + 0 × 3 1 + ( − 1 ) × 3 0 = 17 1-0-:n=1×3^3+(- 1)×3^2+0×3^1+(-1)×3^0=1710=1×33+( 1 )×32+0×31+( 1 )×30=17

最終的に 10 進数の 17 に変換されることがわかります。

最後に、もう 1 つ注意すべき点があります。3 進数における負の数と正の数の変換関係のバランスを取ることです。実際、タイトルにはそれらの間の関係についてのヒントも含まれています。「3 進コードの特性の 1 つは対称性、つまり反対の数の一貫性です。」バランスの取れた 3 進数の場合、その反対の数とそれ自体との関係は次のとおりです。ゼロ以外のデータはすべて互いに反対ですたとえば、平衡型 3 進数 の場合1-01、対応する負の数は次のようになります-10-

1 − 01 : n = 1 × 3 3 + ( − 1 ) × 3 2 + 0 × 3 1 + 1 × 3 0 = 27 − 9 + 0 + 1 = 19 1-01:n=1×3^3+ (-1)×3^2+0×3^1+1×3^0=27-9+0+1=19101 n=1×33+( 1 )×32+0×31+1×30=279+0+1=19
− 10 − : n = ( − 1 ) × 3 3 + 1 × 3 2 + 0 × 3 1 + ( − 1 ) × 3 0 = − 27 + 9 + 0 − 1 = − 19 -10-:n= (-1)×3^3+1×3^2+0×3^1+(-1)×3^0=-27+9+0-1=-19−10 _=( 1 )×33+1×32+0×31+( 1 )×30=27+9+01=−19 _

上記の分析によれば、この問題を解決するためのアイデアは次のように整理できます。

  1. 入力された 10 進数を対応する 3 進数に変換します (処理を容易にするために、このステージでは一律に正の数を使用します)。
  2. 3 進数を平衡 3 進数に変換します。変換規則は次のとおりです (現在の 3 進数文字列が num であると仮定します)。
    • num[i] = 2 の場合、num[i] = -, num[i+1]++ を設定します (数値文字列のインデックス サイズは、数値の下位ビットから上位ビットに対応します)。
    • num[i] = 3 の場合、num[i] = 0、num[i+1]++。
  3. 入力 10 進数の符号に従って、結果の平衡 3 進数がそれに応じて処理されます。

以下は、上記の考え方に基づいた完全なコード (すでに AC です) です。

/*
	MT2190 三进制计算机2  
	思路:先将数从十进制转换至正常的三进制,然后再转换为平衡三进制 
*/
#include<bits/stdc++.h> 
using namespace std;

const int N = 55;
int num[N], n, x, flag, cnt;

int main( )
{
    
    
	// 取消cin与stdin的同步(加速文件读取速度) 
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	// 输入数据
	cin>>n; 
	while(n--){
    
    
		cin>>x;
		memset(num, 0, sizeof(num));
		flag = 1, cnt = 0;
		// 程序将统一处理正数,因此定义标记来记录原始输入数据的正负性 
		if(x<0){
    
    
			flag = -1;
			x = -x;
		}
		if(x == 0){
    
    
			cout<<x<<"\n";
			continue;
		} 
		// 将十进制数转换为三进制数 
		while(x){
    
    
			num[cnt++] = x%3;
			x /= 3;
		}
		// 将三进制数转换为平衡三进制数 
		for(int i=0; i<cnt; i++){
    
    
			if(num[i] == 2){
    
    
				// 借位 
				num[i] = -1;
				num[i+1]++;
			}else if(num[i] == 3){
    
    
				// 进位 
				num[i] = 0;
				num[i+1]++; 
			}
		}
		// 判断原始三进制数转换为平衡三进制数后是否出现了位增情况 
		if(num[cnt]) cnt++;
		// 如果原始输入的十进制数为负数,则需要对已经算出的平衡三进制数进行反号 
		if(flag == -1) 
			for(int i=cnt-1; i>=0; i--)
				num[i] = -num[i];
		// 输出转换后的平衡三进制数,需要进行格式控制:所有的-1都输出- 
		for(int i=cnt-1; i>=0; i--)
			if(num[i] == -1) cout<<"-";
			else cout<<num[i];
		cout<<"\n";
	}
	
    return 0;
}

終わり


おすすめ

転載: blog.csdn.net/the_ZED/article/details/132366931