目录
- 题目
- 官方给的解题思路
- 源代码
- 附
- 最大公因数
- 辗转相除法
- 更相减损术
- 所有因数
- 参考文献
题目
给定斜边z的值,求所有直角边x和y的组合数(x、y和z都是正整数)。
仅有一行输入,即斜边z的值(z是正整数,且z<10000000000000000000)
输出x和y的组合数(x和y是正整数)
时间限制:1000ms
内存限制:256M
官方给的解题思路
源代码
根据官方思路,编的第一版:
def main(c):
group = set()
g_list = get_factor(2*c)
for g in g_list:
n = (2*c)/g
for x1 in range(1, int(n**0.5)+1):
y1 = (n - x1**2)**0.5
_y1 = y1 - int(y1)
if _y1 == 0 and y1 > x1:
x = g*x1**2
y = g*y1**2
a = int((x*y)**0.5)
b = int(abs(x-y)/2)
group.add((a, b))
return len(group)
def get_factor(n):
r = []
x = 1
while x < n:
if n % x == 0:
r.append(x)
x += 1
return r
if __name__=='__main__':
z = input()
nums = main(int(z))
print(nums)
根据官方思路,编的第二版,修改了计算因数部分的代码,代码通过~
def main(c):
group = set()
g_list = get_factor(2*c)
for g in g_list:
n = (2*c)/g
for x1 in range(1, int(n**0.5)+1):
y1 = (n - x1**2)**0.5
_y1 = y1 - int(y1)
if _y1 == 0 and y1 > x1:
x = g*x1**2
y = g*y1**2
a = int((x*y)**0.5)
b = int(abs(x-y)/2)
group.add((a, b))
print(group)
return len(group)
def get_factor(c):
r = []
x = 1
while x <= c**0.5:
if c % x == 0:
r.append(x)
if c//x != x:
r.append(c//x)
x += 1
return r
if __name__=='__main__':
z = input()
nums = main(int(z))
print(nums)
附
最大公因数
辗转相除法
又名欧几里得算法(Euclidean algorithm),目的是求出两个正整数的最大公约数。
两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。比如10和25,25除以10商2余5,那么10和25的最大公约数,等同于10和5的最大公约数。
def gcd(a, b):
m = max(a, b)
n = min(a, b)
r = m % n
while r != 0:
m = n
n = r
r = m % n
return n
更相减损术
出自于中国古代的《九章算术》,也是一种求最大公约数的算法。
两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。比如10和25,25减去10的差是15,那么10和25的最大公约数,等同于10和15的最大公约数。
def gcd(a, b):
while a != b:
if a > b:
a -= b
else:
b -= a
return a
所有因数
def get_factor(c):
r = []
x = 1
while x <= c**0.5:
if c % x == 0:
r.append(x)
if c//x != x:
r.append(c//x)
x += 1
return r
参考文献
https://bbs.csdn.net/topics/616088159
密码学学习笔记 之 数论四大定理及应用