簡體   English   中英

這個C ++代碼和這個Python代碼有什么區別?

[英]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_clzlunsigned long參數和__builtin_clzllunsigned long long 。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM