PAT A1010-基数(二分法)

PAT A1010-基数(二分法)

カジュアルワーキング

正の整数の組を考えると、例えば、図6および110は、この式(6)= 110が真であることができますか?答えはyes6は、小数点数であり、110は二進数であれば、。

今、正の整数のいずれかのペアのN 1およびN 2は、あなたのタスクは、他のものを与えている間に1数の基数を見つけることです。

入力仕様:

各入力ファイルには、1つのテストケースが含まれています。各ケースは4つの正の整数を含む行を占めています。

N1 N2 tag radix

ここでN1N2、それぞれには10個の以上の数字を持っていません。数字は、以下の基数よりもセット{0-9、から選択されるa- z} 0-9進数0-9を表し、a- z小数点数10-35を表します。最後の数字は、radixの基数であるN1場合はtag1であり、またはN2場合tag2です。

出力仕様:

式はそのように、各テストケースのために、一列に他の数の基数を印刷N1= N2真です。式が不可能な場合は、印刷しますImpossible解決策が一意でない場合は、出力可能な最小基数。

サンプル入力1:

6 110 1 10

サンプル出力1:

2

サンプル入力2:

1 ab 1 2

出力例2:

Impossible

図4は、実質的に、最初の数の数であるN1、第二の数N2、第3の数は、tag正面を示しN1N2最後の数が前記radix示す塩基であるtag基数数が指定された数です。

これらのデータにより、我々は作り、最小限の基盤を見つける必要があるN1= N2設立します。

上記の例では、N1 = 6、、 、N2 = 110 本明細書に記載されるように、すなわち進番号10の塩基数であり、それは計算により発見されたバイナリ数の、同じ値。2が出力されます。tag = 1radix = 10N1N2N1N2

問題解決のためのアイデア

この質問は、比較を含むが、ここではN1N2私たちN1、N2は比較するための十進数に変換されているので、別の16進数を含むことができます。N1簡単進数に変換するために、N2我々はベースの複数横断する必要がありradix、計算に対応する塩基、N2小数の値、その後N1比較し、それらが等しい場合、それは我々が探していることであってもよいですradix

その後、のためにradix複数のパスを取得する必要がありますので、ここで私たちは二分法を使用しています。これは、第1の境界値を決定する必要があり、下限はleftカジュアルな作業に応じて、決定することは容易である「A digit is less than its radix and is chosen from the set」情報がちょうど見つける必要がある与えられN2た最大値をdigit--max、その後は順番ににすることができleft = max + 1、ボーダーのためにright、2つの方法があります:1、left2によって疲れ、非常に多くのことを数サイクル後に知ることができます。塩基数として計算前N2より少ない小数点値よりもN1、塩基として計算し、この数と現在のN2小数点値よりも大きい場合はN2、それが上限であると知ることができる、などの現在選択された数が見出さright缶。2、直接方法があるN1として計算上限プラス小数点値rightこの理論的根拠はあるのright上限ベース、決定基数-1ごとでdigit、上限を設定がある場合はこれだけ、重要なを取るright少なく、この値よりも、そのときN2の時間が唯一のもので、Aの値はいえすでにに等しいN1小数の計算が、上限によって制限され、正解に到着しません。場合N2の数、ゼロでない値で、最後の1で、この値が存在し、それを行うことができるright服用でradix、小数点の結果を時間よりも大きくなければならないN1ので、権利があるかどうかことを保証することのradix私達の設定した間隔で、それが含まれている必要があります内部。

データは10個のテストポイントは、複数の提出が通過し、最終的に変更することができない非常に大規模な操作ですので、基本的な考え方と、それから、非常に重要な点は、大きな選択する変数の整数、そこにあるlong longunsigned long long

コード

#include <stdio.h>
#include <string.h>

using namespace std;
// 把字符串转化为十进制数
unsigned long long int stod(char snum){
    if(snum <= '9' && snum >= '0') return snum - '0';
    return snum - 'a' + 10;
}
// 计算数字N的十进制数值
unsigned long long int compute(int len, char *N, unsigned long long int radix){
    unsigned long long int sum = 0;
    for(int i = 0; i < len; i++){
        sum = sum * radix + stod(N[i]);
    }
    return sum;
}

int main() {
    char N[2][11];
    int tag, len[2];
    unsigned long long int right, left = 0, mid, radix, sum, osum = 0, theother;

    // 读取数据
    scanf("%s %s %d %lld",N[0], N[1], &tag, &radix);
    len[0] = (int)strlen(N[0]);
    len[1] = (int)strlen(N[1]);
    
  	//N1-0;N2-1于是当tag=1->N1,另一个就是theother = 2-1 =1->N2
    theother = 2-tag;
    tag = tag - 1;

    sum = compute(len[tag], N[tag], radix);// 计算tag指定的目标字符串代表的数的十进制值
    for(int i = 0; i < len[theother]; i++){// 找到另一个字符串的最大值
        if(left < stod(N[theother][i])) left = stod(N[theother][i]);
    }
  	// 边界值确定
    left += 1;
    right = sum + 1;
    
    while (left <= right){
        mid = (left + right) / 2;
        osum = compute(len[theother], N[theother], mid);
        if(osum > sum){
            right = mid - 1;
        }
        else if(osum < sum){
            left = mid + 1;
        }
        else if(osum == sum){
            printf("%lld", mid);
            return 0;
        }
    }
    printf("Impossible\n");
    
    return 0;
}

发布了9 篇原创文章 · 获赞 1 · 访问量 185

おすすめ

転載: blog.csdn.net/weixin_41515197/article/details/104119070