割り切れるラッキーナンバー
トピックの説明
ラッキーナンバーが 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;
}