给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。要求:空间复杂度O(1)
其实原理很简单,奇数和偶数必定成对的交换位置。
# values = [1, 3, 5, 7, 2, 4, 6, 9, 11, 8, 10]
values = [1, 2, 3, 4, 5, 6, 7, 8, 20, 19, 18, 17, 16]
# left: odd
# right: even
def partition(values)
low = 0
high = values.size - 1
while low < high
if 0 == (values[low] % 2)
while 1 != (values[high] % 2)
high = high - 1
end
if high > low
values[low], values[high] = values[high], values[low]
end
elsif
low = low + 1
end
end
end
partition(values)
puts(values)
http://projecteuler.net/index.php?section=problems&id=72
欧拉函数本身的计算并不困难,但是1到1,000,000,要想算得快的话就必须利用以下推论:
若(N%a==0 && (N/a)%a==0) 则有:Phi(N)=Phi(N/a)*a;
若(N%a==0 && (N/a)%a!=0) 则有:Phi(N)=Phi(N/a)*(a-1);
(这里a为质数)
有了这个推论,我们就可以用空间换时间来解决。代码写的不是很好,大概8秒不到能得到结果。这里使用筛法求1,000,000以内素数。
from math import sqrt
MAX_LIMIT = 1000000
R_MAX_LIMIT = sqrt(MAX_LIMIT)
prime_list = []
prime_mask = [] # start from 2 to 1,000,000
phi_cached = {}
def Phi(number):
if number in phi_cached:
return phi_cached[number]
if 0 != prime_mask[number - 2]:
phi_cached[number] = number - 1
return phi_cached[number]
else:
root = sqrt(number)
for i in range(0, len(prime_list)):
p = prime_list[i]
if p > root:
break;
if 0 == (number % p):
minor = number // p
if 0 == minor % p:
phi_cached[number] = Phi(minor) * p
else:
phi_cached[number] = Phi(minor) * (p - 1)
return phi_cached[number]
# build prime list/mask
for i in range(2, MAX_LIMIT + 1):
prime_mask.append(i)
for i in range(0, len(prime_mask)):
p = prime_mask[i]
if p != 0:
index = p * 2
while index <= MAX_LIMIT:
prime_mask[index - 2] = 0
index += p
for i in range(0, len(prime_mask)):
if prime_mask[i] > R_MAX_LIMIT:
break
if 0 != prime_mask[i]:
prime_list.append(prime_mask[i])
sum = 0
for i in range(2, MAX_LIMIT + 1):
sum += Phi(i)
print("sum = %d" % sum)
http://projecteuler.net/index.php?section=problems&id=65
Python真是个好东西,再也不用为大数操心了。
e_list = [2]
def Add(number, up, down):
return number * down + up, down
def CalcTemp(start, end):
if (start + 1) == end:
up, down = Add(e_list[start], 1, e_list[start + 1])
return up, down
else:
up, down = CalcTemp(start + 1, end)
up, down = down, up
return Add(e_list[start], up, down)
def Resolve(end):
up, down = CalcTemp(1, end)
up, down = down, up
return Add(e_list[0], up, down)
for i in range(1, 100):
if 2 == (i % 3):
e_list.append(2 * (i // 3 + 1))
else:
e_list.append(1)
up, down = Resolve(99)
print("up = %d\n" % up)
print("down = %d\n" % down)
sum = 0
while up > 0:
sum += up % 10
up //= 10
print("sum = %d\n" % sum)
- 时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
- 计算a的b次方对9907取模的值。
- 输入
- 第一行有一个正整数T,表示有T组测试数据。
接下来T行,每行是一组测试数据,包含两个整数a和b。
其中T<=10000, 0 <=a,b < 2^31。 - 输出
- 有T行,依次输出每组数据的结果。
- 样例输入
-
3
1 2
2 3
3 4 - 样例输出
-
1
8
81
虽然a和b给出的范围很大,但自己先列下式子比划一下,其实题目还是非常简单的。
令c=9907,把a写成a=xc+y,那么(a^b)%c根据2项式展开就应该等于(y^b)%c。如果a比较大的话,就可以降解成一个比较小的值了。
但是如果b也巨大无比怎么办呢?任取一数A = Xc + Y; A^2 =(Xc)^2+2XYc+Y^2,这个数对c取2模就是Y^2也就是A%c。如果b是偶数,就先对a^(b/2)取模,再把结果相乘再取模。如果是奇数呢?那就把a^(b-1)的结果算出来,假设结果A=Xc+Y,再乘以a=xc+y,那么最终结果就是(Yy)%c。那么,现在就拜托递归了。
#include <stdio.h>
int calcMod(int a, int b, int c)
{
int b1;
int x;
if (a >= c)
{
return calcMod(a % c, b, c);
}
if (a == 1)
{
return 1;
}
if (a == 0)
{
return 0;
}
if (b == 1)
{
return a;
}
if (b == 0)
{
return 1;
}
b1 = b / 2;
x = calcMod(a, b1, c);
if (1 == (b % 2))
{
return (x * x * (a % c)) % c;
}
else
{
return (x * x) % c;
}
}
int main(void)
{
int a = 17, b = 30;
int c = 9907;
printf("%d^%d mod %d = %d\n", a, b, c, calcMod(a, b, c));
}
前段时间对测试代码的编译环境做了一些修改,在做free build的时候取消了_DEBUG/DEBUG的定义。最近跑test时出了一个以前从为出现过的错误,debug后发现if/else的工作不正常,在if已经判断为true后还是进入了else。想到某人数月前抱了一个编译环境的bug,难道这种小概率事件也降临到我头上。经过N小时反复研究代码,终于发现了问题的症结所在。
先看一下以下这段define(实际代码略复杂,此处做了简化):
#ifdef _DEBUG
#define TRACE printf
#else
#define TRACE if (0) printf
#endif
有问题吗?貌似OK,如果是free build就不执行printf。事实上在大多数情况下都没什么问题,但是再看看以下代码:
if (1)
TRACE("OK\n");
else
printf("Why?\n");
在Visual Studio中分别用DEBUG和RELEASE编译看看运行结果,是不是比较奇怪?
其时,在_DEBUG没有被define的情况下,宏展开后的代码是这样的:
if (1)
if (0)
printf("OK\n");
else
printf("Why\n");
因为TRACE后面跟不定参数,我们无法使用"#define TRACE ",考虑到尽可能减少对现有代码的影响,修改为"#define TRACE while (0) printf"。
以上代码绝非新手所为,即使是老鸟偶尔还是会阴沟里翻船^_^怪不得老大总是说我们的test当年free build没法跑,最后只跑chk build。

