题目描述
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1143
构造法
不是很会证为什么很快出解……
随机a[1~n]和b[1~m],使得a与b内均未有重复元素,且和为完全平方数,且每一项均为完全平方数。在400^2内随机即可。
然后c[i,j]=a[i]*b[j],检验重复即可。
详见代码。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn=20+10;
const ll d=1e17;
ll a[maxn],b[maxn],o[maxn],c[maxn][maxn],f[maxn*maxn],dd,ddd,sq[500];
bool bz[410];
int i,j,k,l,t,n,m,tot;
bool czy;
ll random(ll x){
ll t=rand()%10000;
t=t*10000+rand()%10000;
t=t*10000+rand()%10000;
t=t*10000+rand()%10000;
return t%x;
}
bool issqr(int x){
db t=floor(sqrt(x));
t=t*t;
if (t!=x) return 0;else return 1;
}
void make(ll *a,int n){
int i,k,sum;
bool czy=0;
fo(i,1,ddd) bz[i]=0;
while (1){
czy=0;
sum=0;
fo(i,1,n-1){
while (1){
k=random(ddd)+1;
if (!bz[k]) break;
}
bz[k]=1;
o[i]=k;
a[i]=sq[k];
sum+=sq[k];
}
fo(i,1,ddd)
if (!bz[i]&&issqr(sum+sq[i])){
czy=1;
a[n]=sq[i];
break;
}
if (czy==1) break;
fo(i,1,n-1) bz[o[i]]=0;
}
}
int main(){
dd=floor(sqrt(d));
//ddd=floor(sqrt(dd));
ddd=400;
fo(i,1,ddd) sq[i]=i*i;
scanf("%d%d",&m,&n);
while (1){
czy=1;
make(a,n);
make(b,m);
//fo(i,1,n) a[i]=a[i]*a[i];
//fo(i,1,m) b[i]=b[i]*b[i];
/*fo(i,1,n)
if (!issqr(a[i])){
czy=0;
break;
}
fo(i,1,m)
if (!issqr(b[i])){
czy=0;
break;
}*/
/*fo(i,1,n)
fo(j,1,m)
if (a[i]>d/b[j]){
czy=0;
break;
}
else c[i][j]=a[i]*b[j];*/
fo(i,1,n)
fo(j,1,m)
c[i][j]=a[i]*b[j];
//if (!czy) continue;
tot=0;
fo(i,1,n)
fo(j,1,m)
f[++tot]=c[i][j];
fo(i,1,tot)
fo(j,i+1,tot)
if (f[i]==f[j]){
czy=0;
break;
}
if (czy){
fo(i,1,n){
fo(j,1,m)
printf("%lld ",c[i][j]);
printf("\n");
}
break;
}
}
}