LetCode を磨いても大丈夫 - 割り切れるラッキーナンバー

割り切れるラッキーナンバー

トピックの説明

ラッキーナンバーが 7、47 など、4 または 7 のみを含む正の整数であると仮定します。正の整数が幸運な数字で割り切れるかどうかを判断します。ある場合はYESを出力し、そうでない場合はN0を出力します。負の数、0、またはその他の特殊な場合は考慮されません。流出や整数の範囲を超える場合は考慮しません。

例 1:

输入:47
输出:YES
解释:47能被幸运数47整除 。

ブルートフォースソリューション:

1から入力nまで、nの約数をすべてたどって、吉数かどうかを1つずつ判定し、吉数であればYES、そうでなければNOを出力します。(暴力的な解決策は単純すぎるため、実装方法はここでは示しません。)

ラッキーナンバートラバースメソッド:

すべてのラッキーナンバーをリストし、入力とこれらのラッキーナンバーの間の余りによって、入力がラッキーナンバーで割り切れるかどうかを判断する方法を見つける必要があります。ラッキーナンバーが均等に割り切れる場合は、NO を出力します。

幸運な数字を得る

ここで、次のような問題があると仮定します。ラッキー ナンバーが 7、47 など、4 または 7 のみを含む正の整数であるとします。指定された値 K を通じて、K 番目に大きい幸運の数字を取得する必要があります。たとえば、1 が与えられた場合、それは 4 になり、8 が与えられた場合、それは 447 になります。次に、この問題を解決する必要があります。

以下のような木があるものとします。
ここに画像の説明を挿入
次に、K 値が与えられると、必要な数値は次のステップにマッピングされます。

1: この数値はツリー内のどの層にあるか、つまり h=int(log2(K+1)+1)
2: h 番目の層の上に数値は合計でいくつあるか、つまり num=pow(2, h- 1) - 1、これには意味のないプライマリ ノードが含まれていることに注意してください。
3: 0 から始まる h 層の番号はどれですか。たとえば、444 は第 4 層の 0 番目の番号です。つまり、idx=K-num

この時点で、8 番目の数値 (447)、つまり h=int(log2(8+1)+1)=4; num=
pow(2,4-1)-1=7;を取得したいとします。 idx= 8-7=1;
つまり、4 階の最初のポイントです。
4 番目の層では、この数値は 3 桁の数値でなければならないことがわかっています。1 は 2 進数の 001 に変換でき、
0 は 4 に対応し、1 は 7 に対応します。すると、001 は 447 になります。それは解決されました。

手順は次のとおりです。

# 翻转整数值 例:123->321
int reverseNum(int num) {
    
    
	int result = 0, temp;
	while (true) {
    
    
		if (num != 0) {
    
    
			temp = num % 10;
			result = result * 10 + temp;
			num = num / 10;
		}
		else {
    
    
			break;
		}
	}
	return result;
}

# 从小到大获取第K大的幸运数
int getLuckyNum(int K) {
    
    
	int h, num;
	# 求得层数
	h = log2(K + 1) + 1;
	# 求得前几层的总共节点数
	num = pow(2, h - 1) - 1;
	# 求得是第h层的第几个,从0开始
	int idx = K - num;
	int ans = 0;
	for (int i = 0; i < h - 1; i++) {
    
    
		# 与最低位取并集,为1就是7,为0就是4
		if ((idx & 1) == 0) {
    
    
			ans = ans * 10 + 4;
		}
		else {
    
    
			ans = ans * 10 + 7;
		}
		idx = idx >> 1;
	}
	# 翻转数值,获得最终的幸运数
	ans = reverseNum(ans);
	return ans;
}

ラッキーナンバートラバース法

int reverseNum(int num) {
    
    
	int result = 0, temp;
	while (true) {
    
    
		if (num != 0) {
    
    
			temp = num % 10;
			result = result * 10 + temp;
			num = num / 10;
		}
		else {
    
    
			break;
		}
	}
	return result;
}

int getLuckyNum(int K) {
    
    
	int h, num;
	h = log2(K + 1) + 1;
	num = pow(2, h - 1) - 1;
	int idx = K - num;
	int ans = 0;
	for (int i = 0; i < h - 1; i++) {
    
    
		if ((idx & 1) == 0) {
    
    
			ans = ans * 10 + 4;
		}
		else {
    
    
			ans = ans * 10 + 7;
		}
		idx = idx >> 1;
	}
	ans = reverseNum(ans);
	return ans;
}

int main( )
{
    
    
    int n, ans;
    # 输入数值
    scanf("%d", &n);
    for (int i = 1; i<=n; i++){
    
    
     	# 遍历幸运数
        ans = getLuckyNum(i);
        # 如果幸运数比输入还大,则该数不能被任意幸运数整除。
        if (ans > n){
    
    
            printf("NO");
            break;
        }
        else{
    
    
        	# 如果输入能被幸运数整除,则输出YES。
            if (n % ans == 0){
    
    
                printf("YES");
                break;
            }
        }
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/REstrat/article/details/128499319