博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
三角形
阅读量:4978 次
发布时间:2019-06-12

本文共 1494 字,大约阅读时间需要 4 分钟。

Portal --> who knows qwq

Description

  给你\(n\)条边,长度都不超过\(A\),问有多少种选边的方案满足这三条边能构成一个直角三角形

  数据范围:\(1<=n<=10^6,1<=A<=10^5\)

  

Solution

  我的小学数学可能白学了qwq

  

  直觉是。。直接枚举勾股数但是这个东西要怎么枚举呢。。。

  有两种方法:

  第一种是对于所有的满足\(gcd(x,y,z)=1\)\(x^2+y^2=z^2\)的三元组,它的解可以写成:

\[ \begin{cases} x=t(a^2-b^2)\\ y=2tab\\ z=t(a^2+b^2) \end{cases} \]
  所以我们枚举这个\(a\)\(b\)就好了,然后倍数跳上去。。

​   

​  第二种方法是如果说你不知道上面的这个结论,那么可以直接简单处理一下式子:

\[ \begin{aligned} x^2+y^2&=z^2\\ x^2&=z^2-y^2\\ &=(z-y)(z+y) \end{aligned} \]
  所以我们可以枚举\(x\),然后枚举\(x^2\)的因数就好了qwq

  

​  mark:主要是mark一下上面那个勾股数的结论qwq

  

​  第一种方法的代码大概长这个样子

#include
#include
#include
#include
#define ll long longusing namespace std;const int N=1e6+10,MOD=998244353;int a[N];int cnt[N];int n,m,ans;int mul(int x,int y){return 1LL*x*y%MOD;}int plu(int x,int y){return (1LL*x+y)%MOD;}int gcd(int x,int y){return y?gcd(y,x%y):x;}int main(){#ifndef ONLINE_JUDGE freopen("a.in","r",stdin);#endif ll x,y,z; scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%lld",&x),++cnt[x]; for (int i=1;i*i<=m;++i){ for (int j=1;j<=i;++j){ x=1LL*i*i-1LL*j*j; y=1LL*2*i*j; z=1LL*i*i+1LL*j*j; if (z>m) continue; if (gcd(x,gcd(y,z))>1) continue; for (int x1=x,y1=y,z1=z;z1<=m;x1+=x,y1+=y,z1+=z) ans=plu(ans,mul(cnt[x1],mul(cnt[y1],cnt[z1]))); } } printf("%d\n",ans);}

转载于:https://www.cnblogs.com/yoyoball/p/9871451.html

你可能感兴趣的文章