题目
有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;
}