• 三角形


    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)的三元组,它的解可以写成:

    [egin{cases} x=t(a^2-b^2)\ y=2tab\ z=t(a^2+b^2) end{cases} ]

      所以我们枚举这个(a)(b)就好了,然后倍数跳上去。。

    ​   

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

    [egin{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<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define ll long long
    using 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
    ",ans);
    }
    
  • 相关阅读:
    12小时制时间
    sqlserver 安装和配置
    建议71:区分异步和多线程应用场景
    AVD管理器提示:PANIC:Could not open:AVD名称 解决办法
    一道看似复杂但是简单的c#面试题
    XML Schema 配置文件自动生成c#类设计案例子
    VS2010中的调试技巧 断点
    文章已被删除
    使用MONO使.net程序脱离.net框架运行
    5个很好用的.net 分析工具
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9871451.html
Copyright © 2020-2023  润新知