ABC081B - Shift only

题目

有N个整数,对它们进行除以2的操作,直到有数变成奇数为止,输出最多的操作次数。


入力例

3
8 12 40

出力例 

2

自己的思路:需要判断有无奇数、进行除操作、计算操作的次数

n = int(input())
a = list(map(int, input().split()))
 
c=0
while(1):
    f=True
    for i in range(n): #判断是否存在奇数
        if a[i]%2!=0:
            f=False
            break
    if f==False: # 存在奇数,利用f跳出二重循环
        break
    if f:
        c+=1
        for j in range(n):# 除操作
            a[j]=a[j]/2
print(c)

更简单的写法:用一行语句写循环

n = int(input())
a = list(map(int, input().split()))
ans = 0
while True:
  if [i for i in a if i % 2 == 1]: # 是否存在奇数
    break
  a = [i/2 for i in a] # 每个元素除以2
  ans += 1
print(ans)

但题目叫做Shift Only,所以显然是希望用移位的原理进行计算的。

二进制数除以2=右移一位,例如1100(12)->110(6)。所以计算使二进制数的最后一位为1的移位次数就可以了,也就是说要计算移位了右边几个0。

n = int(input())
a = list(map(int, input().split()))

for i in a:
    # len(bin(i))=位数
    # rfind()返回字符最后一次出现的位置,即从右数第一次出现的位置
    # 因为从0记位置所以最后再-1
    ans = min(ans, len(bin(i)) - bin(i).rfind("1") - 1)
print(ans)

甚至有更简单的写法:

# bin(a)[::-1]前后翻转,例如将 0b10100 翻转为 00101b0
print(min(bin(i)[::-1].find("1") for i in a))

C++版本的官方解答:

#include <iostream>
using namespace std;

int N;
int A[210];         // 最大 200 個なので余裕を持って 210 に --- 200 以上ならなんでもよいです

int main() {
    cin >> N;
    for (int i = 0; i < N; ++i) cin >> A[i];

    int res = 0;

    // 操作が行える限り操作を繰り返す
    while (true) {
        bool exist_odd = false;  // A[i] がすべて偶数かどうかを判定するフラグ
        for (int i = 0; i < N; ++i) {
            if (A[i] % 2 != 0) exist_odd = true;  // 奇数があったらフラグを立てる
        }

        if (exist_odd) break;  // 奇数があったら break

        // 操作を行えるなら操作を実際に行う
        for (int i = 0; i < N; ++i) {
            A[i] /= 2;
        }
        ++res;  // 操作回数をインクリメント
    }

    cout << res << endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_43019673/article/details/121782468
今日推荐