[英]What is the difference between this C++ code and this Python code?
感謝@TheDark發現溢出。 新的C ++解決方案也非常有趣。 這是極其多余的:
if(2*i > n && 2*i > i)
替換了代碼的舊行if(2*i > n)
。
我正在HackerRank上解決此問題 ,盡管該問題可能並不完全與此問題相關。 如果您看不到該網頁,或者必須創建帳戶而又不想這樣做,則該問題將在下面的純文本中列出。
我的C ++代碼超時,但是我的python代碼沒有超時。 我首先懷疑這是由於溢出造成的,但是我使用sizeof
來確保unsigned long long
可以達到問題的上限2^64 - 1
。
我實際上將C ++代碼直接轉換為Python,以查看是否是導致超時的算法,但令我驚訝的是,我的Python代碼通過了每個測試用例。
C ++代碼:
#include <iostream>
bool pot(unsigned long long n)
{
if (n % 2 == 0) return pot(n/2);
return (n==1); // returns true if n is power of two
}
unsigned long long gpt(unsigned long long n)
{
unsigned long long i = 1;
while(2*i < n) {
i *= 2;
}
return i; // returns greatest power of two less than n
}
int main()
{
unsigned int t;
std::cin >> t;
std::cout << sizeof(unsigned long long) << std::endl;
for(unsigned int i = 0; i < t; i++)
{
unsigned long long n;
unsigned long long count = 1;
std::cin >> n;
while(n > 1) {
if (pot(n)) n /= 2;
else n -= gpt(n);
count++;
}
if (count % 2 == 0) std::cout << "Louise" << std::endl;
else std::cout << "Richard" << std::endl;
}
}
Python 2.7代碼:
def pot(n):
while n % 2 == 0:
n/=2
return n==1
def gpt(n):
i = 1
while 2*i < n:
i *= 2
return i
t = int(raw_input())
for i in range(t):
n = int(raw_input())
count = 1
while n != 1:
if pot(n):
n /= 2
else:
n -= gpt(n)
count += 1
if count % 2 == 0:
print "Louise"
else:
print "Richard"
對我來說,兩個版本看起來相同。 我仍然認為我在某種程度上被愚弄了,實際上在我的C ++代碼中正在溢出,導致超時。
路易絲和理查德玩游戲。 他們的計數器設置為N。路易絲(Louise)得到第一個回合,之后回合交替。 在游戲中,他們執行以下操作。
如果N不是2的冪,則它們會將計數器減小2的最大冪(小於N)。
如果N為2的冪,則它們會將計數器減少N的一半。
結果值是新的N,該N再次用於后續操作。
當計數器減為1(即N == 1)並且最后進行有效舉動的人獲勝時,游戲結束。
給定N,您的任務是找到游戲的贏家。
輸入格式
第一行包含一個整數T,即測試用例的數量。 T線跟隨。 每行包含N,即在計數器中設置的初始數字。
約束條件
1≤T≤10
1≤N≤2 ^ 64-1
輸出格式
對於每個測試用例,在新行中打印獲勝者的姓名。 因此,如果路易絲(Louise)贏得比賽,請打印“路易絲(Louise)”。 否則,打印“ Richard”。 (報價是為了清楚)
樣本輸入
1個
6
樣本輸出
理查德
說明
由於6不是2的冪,因此Louise將2的最大冪減小為小於6的4,即4,因此計數器減小為2。
由於2是2的冪,因此Richard將計數器減2的一半,即1。因此,計數器減為1。
當我們達到N == 1的終止條件時,Richard贏得了比賽。
當n
大於2 ^ 63時,您的gpt
函數最終將i
設為2 ^ 63,然后將2 ^ 63乘以2,從而得到一個溢出值和0。這將導致無限循環,並乘以0每次減2。
試試這個有點混亂的技巧,它可能會稍微快一點:
unsigned long largest_power_of_two_not_greater_than(unsigned long x) {
for (unsigned long y; (y = x & (x - 1)); x = y) {}
return x;
}
x&(x-1)
是x
沒有最低有效位。 因此,恰好在x
減小到2的冪時y
才為零(終止循環),這將是2的最大冪而不大於原始x。 該循環對於x
每個1位執行一次,平均迭代次數是方法的一半。 另外,這個還沒有溢出問題。 (如果原始x
為0,它將返回0。這可能是您想要的,也可能不是。)
請注意,如果原始x
是2的冪,則該值會立即立即返回。 因此,該函數可以作為測試x
是否為2(或0)的冪的兩倍。
盡管這很有趣,但在實際代碼中,最好找到與該內置gcc
等效的編譯器(除非您的編譯器為 gcc
,在這種情況下為):
int __builtin_clz (unsigned int x)
返回X
中從最高有效位開始的前導0位的數目。 如果X
為0,則結果不確定。 (也可作為__builtin_clzl
為unsigned long
參數和__builtin_clzll
為unsigned long long
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.