P2232 [HNOI2002] 填数游戏 题解

P2232 [HNOI2002] 填数游戏 题解

题意

给定 \(n, m\)\(2 \le n, m \le 15\)),在 \(n \times m\) 的矩阵中填入互不相同的完全平方数,使得每行、每列的和均为完全平方数,且所有和小于 \(10^{17}\)

思路

直接搜索显然不可行。令:

\[c_{i,j} = (a_i \cdot b_j)^2 \]

其中数组 \(a\) 满足 \(\sum a_i^2 = S_a^2\),数组 \(b\) 满足 \(\sum b_j^2 = S_b^2\)

则第 \(i\) 行的和:

\[\sum_{j=1}^{m} c_{i,j} = a_i^2 \sum_{j=1}^{m} b_j^2 = a_i^2 \cdot S_b^2 = (a_i \cdot S_b)^2 \]

\(j\) 列的和:

\[\sum_{i=1}^{n} c_{i,j} = b_j^2 \sum_{i=1}^{n} a_i^2 = b_j^2 \cdot S_a^2 = (b_j \cdot S_a)^2 \]

均为完全平方数。问题转化为:构造两个平方和为完全平方数的数组,且所有乘积 \(a_i \cdot b_j\) 互不相同。

我们取前 \(n-1\) 个连续整数 \(st, st+1, \dots, st+n-2\),平方和为 \(s\),找一个 \(x\) 使得 \(s + x^2\) 是完全平方数。

\(s + x^2 = S^2\),则:

\[S^2 - x^2 = s \implies (S-x)(S+x) = s \]

\(d_1 = S-x\)\(d_2 = S+x\),则 \(d_1 \cdot d_2 = s\),且:

\[x = \frac{d_2 - d_1}{2}, \quad S = \frac{d_1 + d_2}{2} \]

枚举 \(s\) 的因子对 \((d_1, d_2)\),要求 \(d_1 < d_2\) 且同奇偶,取 \(x\) 最小且不重复的解。

\(s \bmod 4 = 2\),无法分解为两个同奇偶因子之积,将最后一个数加 \(1\) 即可调整。

先生成 \(a\)\(st = 1\)),再从 \(st = 1\) 逐步尝试生成 \(b\),线性扫描检查所有 \(a_i \cdot b_j\) 是否互不相同。碰撞概率极低,很快就能找到。

复杂度分析

总体复杂度可以近似看成 \(O(\sqrt{s} + (nm)^2)\),实际运行很快。

代码

我的码风真差

#include<bits/stdc++.h>
using namespace std;
long long n,m,ea[20],eb[20],pp[300],pc;
long long fnd(long long x,long long*arr,long long cnt){
    for(long long i=0;i<cnt;++i)if(arr[i]==x)return 1;
    return 0;
}
long long findx(long long s,long long*arr,long long cnt){
    long long sq=(long long)sqrt((double)s);
    for(long long d1=sq;d1>=1;--d1)
        if(s%d1==0){
            long long d2=s/d1;
            if(d1<d2&&(d1+d2)%2==0){
                long long x=(d2-d1)>>1;
                if(x>0&&!fnd(x,arr,cnt))return x;
            }
        }
    return -1;
}
long long gen(long long n,long long st,long long*arr){
    long long cnt=n-1,s=0;
    for(long long i=0;i<n-1;++i)arr[i]=st+i,s+=arr[i]*arr[i];
    if(s%4==2){
        long long last=arr[cnt-1];
        s-=last*last,s+=(last+1)*(last+1),arr[cnt-1]=last+1;
    }
    long long x=findx(s,arr,cnt);
    if(x<0)return 0;
    arr[cnt++]=x,sort(arr,arr+cnt);
    return 1;
}
long long chk(long long*a,long long na,long long*b,long long nb){
    pc=0;
    for(long long i=0;i<na;++i)for(long long j=0;j<nb;++j){
        long long v=a[i]*b[j];
        for(long long k=0;k<pc;++k)if(pp[k]==v)return 0;
        pp[pc++]=v;
    }
    return 1;
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(long long st=1;st<=100000;++st)if(gen(n,st,ea))break;
    for(long long st=1;st<=100000;++st){
        long long tmp[20];
        if(gen(m,st,tmp)&&chk(ea,n,tmp,m)){
            for(long long i=0;i<m;++i)eb[i]=tmp[i];
            break;
        }
    }
    for(long long i=0;i<n;++i){
        for(long long j=0;j<m;++j){
            long long v=ea[i]*eb[j];
            cout<<v*v;
            if(j<m-1)cout<<" ";
        }
        cout<<"\n";
    }
    return ( 0 - 0 );
}
posted @ 2026-07-27 16:13  ブルーヘイロー  阅读(0)  评论(0)    收藏  举报