勾股数
这道题是一对兄弟在几个夜晚里想出来的idea:
弟:哥,这是什么?(指着哥哥远古小本子上的一行字)
哥:哦,那是我初三上课无聊时想的一个“定律”,还没证明,也懒得证明。
弟弟拿出了草稿纸和笔,不到五分钟就证完了。
弟:还挺好证的。
哥:是吗,我不知道。
“定律”原文:
若
则
简证:将
弟:可是它不是强定律捏,看看能不能把这个
哥弟俩花了大概10分钟。
哥:嗯,这个应该没错了。
“强定律”原文:
若
则
证明方法和“非强定律”的证明方法一致。
哥:诶,那如果给定一条边,根据这个定律可以构造出所有的勾股数吗?
弟:……好像可以,如果这条边是
哥:试一试?
弟弟打开了电脑,噼里啪啦了大概20分钟,验证了其正确性。弟弟兴奋不已。
哥:那如果是斜边呢?
两人沉默了一会。
哥:我知道了,
弟弟在刚刚的代码里添加了几行,证明是正确的,两个人十分高兴。
弟:也就是说,现在我们给出一个
哥:对。
形式化的题解:
回到问题,先来分析
令
根据定理,将其化作:
要想求出所有可能的勾股数,即我们要 求出
易知此时
再来分析
令
要想求出所有可能的勾股数,即我们要 求出
易知此时:
所以
综上,总时间复杂度为
#include<cstdio>
#include<cmath>
#define int unsigned long long
int work(int p)
{
int cnt=0,a,b,c,x,y,n;
a=p;
// for(x=1;x<=p-1;x++)//枚举x
// {
// y=a-x;
// n=y-x;
// if(n>0&&(2*x*x)%n==0)
// {
// b=(x*x+y*y)/n-n;
// c=(x*x+y*y)/n;
// cnt++;
// }
// }
for(n=1;n<=p-1;n++)//枚举n
{
if((p-n)%2) continue;
x=(p-n)/2;
y=x+n;
if(x<y&&(2*x*x)%n==0)
{
b=(x*x+y*y)/n-n;
c=(x*x+y*y)/n;
cnt++;
}
}
c=p;
for(n=1;n<2*p;n++)
{
int tmp=2*c*n-n*n;
int b=c-n;
a=sqrt(tmp);
if(a*a==tmp&&c>n&&a<b) cnt++;
}
return cnt;
}
signed main()
{
int t;
scanf("%llu",&t);
while(t--)
{
int p;
scanf("%llu",&p);
printf("%llu\n",work(p));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构