kmjp's blog

競技プログラミング参加記です

RCC 2014 Warmup - Div1 C. Square Table

面白い問題だった。
http://codeforces.com/contest/418/problem/C

問題

数N,Mが与えられるので、以下の条件を満たすNxMの行列を返せ。

  • 各要素は1~10^8の整数
  • 各行について、行内各要素の二乗和を取ると平方数である
  • 各列について、列内各要素の二乗和を取ると平方数である

解法

二乗和を取ると平方数となるような整数群があったとすると、全体を整数倍してもやはり二乗和は平方数となる。
例えば3^2+4^2+12^2+84^2 = 85^2なら、全体を2倍しても2^2*(3^2+4^2+12^2+84^2)=(2*85)^2で成り立つ。

よって、N要素の整数群とM要素の整数群を掛け合わせればよい。
例えば4要素なら先の3^2+4^2+12^2+84^2=85^2、3要素なら2^2+3^2+6^2=7^2なのでこんな感じでNxMの行列を生成できる。

   3  4 12  84
 -------------
2| 6  8 24 168
3| 9 12 36 252
6|18 24 72 504

問題は、N要素とM要素の整数群を求めることである。
幸い、1~100要素については2要素以外は1と2と3だけで生成できるので、総当たりで候補を探せばよい。
2要素の時は(3,4)を用いる。

int N,M;
vector<int> MM[101];
void solve() {
	int f,i,j,k,l,x,y,z;
	
	cin>>N>>M;
	MM[1].push_back(1);
	MM[2].push_back(3);
	MM[2].push_back(4);
	FOR(x,101) FOR(y,101) FOR(z,101) {
		if(x+y+z>=3 && x+y+z<=100) {
			int hoge=x+y*4+z*9;
			int aa=sqrt(hoge+0.1);
			while(aa*aa<hoge)aa++;
			while(aa*aa>hoge)aa--;
			while(aa*aa<hoge)aa++;
			while(aa*aa>hoge)aa--;
			if(aa*aa==hoge && MM[x+y+z].empty()) {
				FOR(i,x) MM[x+y+z].push_back(1);
				FOR(i,y) MM[x+y+z].push_back(2);
				FOR(i,z) MM[x+y+z].push_back(3);
			}
		}
	}
	FOR(y,N) {
		FOR(x,M) _P("%d ",MM[N][y]*MM[M][x]);
		_P("\n");
	}
}

まとめ

本番気が付けてよかった。