这个C ++代码和这个Python代码有什么区别?

时间:2014-08-06 03:31:14

标签: python c++ algorithm python-2.7

答案

感谢@TheDark发现溢出。新的C ++解决方案也非常有趣。这非常多余:

if(2*i > n && 2*i > i)

替换旧的代码行if(2*i > n)

背景

我正在做this problem on 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.路易斯得到第一个转弯,然后轮流交替。在游戏中,他们执行以下操作。

如果N不是2的幂,它们会将计数器的最大功率减小2,小于N.

如果N是2的幂,它们将计数器减少一半N.

结果值是新的N,它再次用于后续操作。

当计数器减少到1时游戏结束,即N == 1,最后一个进行有效移动的人获胜。

鉴于N,你的任务是找到比赛的胜利者。

输入格式

第一行包含一个整数T,即测试用例的数量。 T线跟随。每行包含N,即计数器中设置的初始数字。

约束

1≤T≤10

1≤N≤2^ 64 - 1

输出格式

对于每个测试用例,请在新行中打印获胜者的姓名。因此,如果路易斯赢得比赛,请打印“路易丝”。否则,打印“理查德”。 (行情是为了清晰起见)

示例输入

1

6

示例输出

理查德

解释

当6不是2的幂时,Louise减小2的最大幂,小于6,即4,因此计数器减少到2。

当2是2的幂时,理查德将计数器减少2的一半,即1.因此,计数器减少到1.

当我们达到N == 1的终止条件时,理查德赢得比赛。

2 个答案:

答案 0 :(得分:4)

n大于2 ^ 63时,您的gpt函数最终将i设为2 ^ 63,然后将2 ^ 63乘以2,得到溢出值和值这将以无限循环结束,每次将0乘以2。

答案 1 :(得分:0)

试试这个有点笨拙的黑客攻击,这可能会稍快一些:

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,没有最不重要的一位。因此,当y减少到2的幂时,x将完全为零(终止循环),这将是不大于原始x的2的最大幂。对x中的每1位执行一次循环,平均迭代次数是方法的一半。此外,这个没有溢出问题。 (如果原始x为0,则返回0.这可能是您想要的也可能不是。)

请注意,如果原始x是2的幂,则只需立即返回该值。因此,该函数兼作x是2的幂(或0)的测试。

虽然这很有趣,但在实际代码中,您可能最好找到与此gcc内置编译器等效的编译器(除非您的编译器 {{ 1}},在这种情况下,它是:)

  • 内置函数:gcc  返回int __builtin_clz (unsigned int x)中从0开始的前导0位数  重要的位置。如果X为0,则结果未定义。

X参数的__builtin_clzlunsigned long的{​​{1}}也可用。)