SRM547 Div1 Medium(500) RectangularSum
Subtableの左上の数字をs、幅をw、高さをhとすると、合計は
S = (1/2)wh( (w-1)+2s+width(h-1) )。
よって、2Sはwhを約数に持つ。2Sの約数の個数は最悪ケース(S=963761198400)でも、7680個なので、wとhの全ての組合わせについて、sを求め、subtableがtable内にあるかを調べる。あまり実行時間に余裕は無いので、最初に約数を求めておかないと間に合わなかった。
#include <algorithm> #include <vector> #include <climits> using namespace std; class RectangularSum{public: long long minimalArea( int height, int width, long long S ) { // 2Sの約数を求める vector<long long> D; for ( long long d=1; d*d<=2*S; d++ ) if ( 2*S%d==0 ) D.push_back(d), D.push_back(2*S/d); sort(D.begin(),D.end()); long long ans = LLONG_MAX; for ( int i=0; i<(int)D.size() && D[i]<=height; i++ ) for ( int j=0; j<(int)D.size() && D[j]<=width; j++ ) if ( 2*S%(D[i]*D[j])==0 ) { long long h = D[i]; long long w = D[j]; long long s = 2*S/w/h - (w-1) - width*(h-1); if ( 0<=s && s%2==0 ) { s /= 2; if ( s%width+w-1 < width && s/width+h-1 < height ) { ans = min(ans,h*w); } } } return ans<LLONG_MAX ? ans : -1; }};