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 );
}

浙公网安备 33010602011771号