HDU 6211 Pythagoras(本原勾股数)

201 篇文章 10 订阅

Description

给出一长度为 2n 2 n 的序列 a0,...,a2n1 a 0 , . . . , a 2 n − 1 ,求 ay mod 2n ∑ a y   m o d   2 n ,其中 y y 满足存在x<y<z109,(x,y,z)=1使得 x2+y2=z2 x 2 + y 2 = z 2

Input

第一行输入一整数 T T 表示用例组数,每组用例首先输入一整数n,之后输入 a0,...,a2n1 a 0 , . . . , a 2 n − 1

(1T3,1n17,1ai255) ( 1 ≤ T ≤ 3 , 1 ≤ n ≤ 17 , 1 ≤ a i ≤ 255 )

Output

ay mod 2n ∑ a y   m o d   2 n

Sample Input

3
2
0 0 0 1
2
1 0 0 0
2
1 1 1 1

Sample Output

39788763
79577506
159154994

Solution

只要找出所有不超过 109 10 9 的本原勾股数即可,对于一组本原勾股数 x2+y2=z2 x 2 + y 2 = z 2 ,先证明几个结论

1. x x ​ y y ​ 互素

d=(x,y)>1 d = ( x , y ) > 1 ,由 z2=x2+y2 z 2 = x 2 + y 2 d2|z2 d 2 | z 2 ,即 d|z d | z ,进而 d|(x,y,z)=1 d | ( x , y , z ) = 1 ,矛盾,故 (x,y)=1 ( x , y ) = 1

2. x,y x , y 一奇一偶

由结论 1 1 知,如果x,y不是一奇一偶则必然为两个奇数,进而 z z 为偶数,假设x=2a+1,y=2b+1,z=2c,由 x2+y2=z2 x 2 + y 2 = z 2 4a2+4a+1+4b2+4b+1=4c2 4 a 2 + 4 a + 1 + 4 b 2 + 4 b + 1 = 4 c 2 ,即 a2+b2c2+a+b=12 a 2 + b 2 − c 2 + a + b = 1 2 ,矛盾,故 x,y x , y 一奇一偶

3.存在奇偶性不同的两个数 s,t s , t 满足 s>t,(s,t)=1 s > t , ( s , t ) = 1 x=s2t2,y=2st,z=s2+t2 x = s 2 − t 2 , y = 2 s t , z = s 2 + t 2

假设 x x 为奇数,y为偶数,则 z z 必然为奇数,x2=z2y2=(zy)(z+y),首先证明 d=(z+y,zy)=1 d = ( z + y , z − y ) = 1

由于 z+y,zy z + y , z − y 均为奇数,故 d d 为奇数,由于d|(z+y+zy)=2z,d|((z+y)(zy))=2y,故 d|y,d|z d | y , d | z ,且注意到 d2|(z+y)(zy)=x2 d 2 | ( z + y ) ( z − y ) = x 2 ,故 d|x d | x ,进而 d|(x,y,z)=1 d | ( x , y , z ) = 1

由于 z+y z + y zy z − y 互素,故 z+y,zy z + y , z − y 为两个互素的完全平方数,设 z+y=m2,zy=n2 z + y = m 2 , z − y = n 2 ,则 x=mn,y=m2n22,z=m2+n22 x = m n , y = m 2 − n 2 2 , z = m 2 + n 2 2 ,其中 m,n m , n 均为奇数且 m>n,(m,n)=1 m > n , ( m , n ) = 1

s=m+n2,t=mn2 s = m + n 2 , t = m − n 2 ,则 s>t s > t 均为正整数,且由于 s+t=m,st=n s + t = m , s − t = n ,故 (s+t,st)=1 ( s + t , s − t ) = 1 ,进而 (s,t)=1 ( s , t ) = 1 ,而 s+t=m s + t = m 为奇数,显然 s,t s , t 一奇一偶,而代入即得 x=s2t2,y=2st,z=s2+t2 x = s 2 − t 2 , y = 2 s t , z = s 2 + t 2

由结论 3 3 ,只要枚举所有的(s,t)即可得到所有的本原勾股数,而由于 z=s2+t2109 z = s 2 + t 2 ≤ 10 9 ,故只需要枚举小范围的 s s ,然后找小于s、与 s s 奇偶性不同且与s互素的 t t <script type="math/tex" id="MathJax-Element-68">t</script>即可

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
const int mod=(1<<17)-1;
int T,n,a[mod+5],f[mod+5];
void init(int N=1e9)
{
    int p[33];
    for(int i=1;i*i<=N;i++)
    {
        int res=0,ii=i;
        for(int j=2;j*j<=ii;j++)
            if(ii%j==0)
            {
                p[res++]=j;
                while(ii%j==0)ii/=j;
            }
        if(ii>1)p[res++]=ii;
        int c=i*i;
        for(int j=1;j<i;j++)
        {
            c+=2*j-1;
            if(c>N)break;
            if(!((i-j)&1))continue;
            int k=0;
            while(k<res&&j%p[k]!=0)k++;
            if(k==res)f[max(i*i-j*j,2*i*j)&mod]++;
        }
    }
}
int main()
{
    init();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        n=(1<<n)-1;
        for(int i=0;i<=n;i++)scanf("%d",&a[i]);
        ll ans=0;
        for(int i=0;i<=mod;i++)ans+=(ll)a[i&n]*f[i];
        printf("%I64d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值