我被困在Project Euler problem 338上。这是我到目前为止所做的......
我们分别表示宽度和高度x
和y
(x,y)
的矩形。要形成新的矩形,您可以考虑使用d步骤沿对角线(如问题描述中所示)切割一种楼梯。但要形成一个新的矩形,必须包含以下内容:d|x
以及(d-1)|y
或(d+1)|y
。然后,新矩形变为(x/d*(d-1), y/(d-1)*d)
或(x/d*(d+1), y/(d+1)*d)
。显然,新的矩形区域与旧矩形的区域相同。
这足以通过循环所有相关的d并将所有新矩形添加到集合中来确认G(10)=55
和G(1000)=971745
,只需谨慎计算(x,y)
和(y,x)
一次。
这种方法的主要问题是可以用两种不同的方式制作一个新的矩形。例如,(9,8)
可以转换为(6,12)
和(12,6)
d=3
以及d-1
或d+1
除以y
。或(4,4)
的另一个示例分别转换为(2,8)
和(8,2)
d=2
和d=1
。
我很幸运地阅读了this blog post。它不需要通过搜索其中一个边来检查重复项。
def F(w, h):
if w&1 and h&1: return 0
if w<h: w,h = h,w
r = 0
x = 1
while x**2 <= w*h:
if (w*h)%x!=0 or x==h:
x += 1
continue
if w%(w-x)==0 or x%(x-h)==0:
r += 1
x += 1
return r
def G(N):
s = 0
for w in range(1, N+1):
for h in range(1, w+1):
s += F(w,h)
return s
无论F有多快,G(10 12 )都需要太长时间才能解决。我认为有必要使用某种筛分算法,我们遍历所有x&lt; 10 12 计算有多少(w,h)满足h <= w <= 10 12 ,x |(w * h),x!= h和( wx)| w或(xh)| x。
我认为O(n 2/3 )算法必须是可能的...但我被困在这里!
修改:我无权访问论坛,因为我无法解决问题。这就是我寻求帮助的原因。我已经完成了大多数其他问题,现在想解决这个问题!
编辑2 :我认为按主要因素考虑区域是一个死胡同。那是因为有10个 24 不同的区域。具有素数区域的矩形具有0个解,具有半素面积的矩形具有1个解,如果其中一个素数为2,否则它们具有0个解。但是,单独计算所有半素溶液将花费太长时间,因为我们需要计算所有质数p,使得2 * p <1。 10 24 这是不可行的。
编辑3 :我已经删除了代码:
def G(N):
s = 0
for x in range(1, N):
for h in range(1, N+1):
if x==h: continue
for w in range(max(h, x**2//h), N+1):
if (w*h)%x==0 and x%(w-x)==0 and x%(x-h)==0:
s -= 1
for x in range(1, N):
for h in range(1, N+1):
if x==h: continue
for w in range(max(h, x**2//h), N+1):
if (w*h)%x==0 and w%(w-x)==0:
s += 1
for x in range(1, N):
for h in range(1, N+1):
if x==h: continue
for w in range(max(h, x**2//h), N+1):
if (w*h)%x==0 and h%(x-h)==0:
s += 1
return s
我认为打破暴力代码不会起作用。记住,我们只计算这三个子问题中的每个子问题的解(x,w,h)就足够了。最后的这种求和将具有约束0 <0。 x&lt; N,0&lt; h&lt; N + 1,x!= h,max(h,x 2 / h)&lt; w&lt; N + 1,x | wh和x-h | h。
我认为我们应该假设一些素数p除以x,w,h甚至x-h,然后看看我们可以推断出其他变量。如果效果很好,可以考虑p k 表示任意k。
答案 0 :(得分:1)
我还没有解决方案,但Python有趣。我意识到Python可以用作算法表示法的便捷工具!基本上我写下了一个类似于你的程序,并开始逻辑地转换程序,使结果保持不变。我想出了
def order(x,y):
if x>=y:
return (x,y)
else:
return (y,x)
N=1000
num=set()
for n in range(1, N+1):
for a in range(1,N//n+1):
for b in range(1,N//(n+1)+1):
if a==b: continue
num.add((order(a*n,b*(n+1)), order(b*n,a*(n+1))))
print(N, len(num))
显然蛮力甚至超过10 ^ 12的简单循环都是不可行的,但是使用这种算法可以在某个时刻找到一个封闭的表达式。如果它不是num的设置字符,那将是可行的。也许人们可以通过这种方式找到重复点。
这可能是一个死胡同,但仍然很酷,Python可用于表示法并使用算法:)
您方面的进展是什么?