ラベル 累積和 の投稿を表示しています。 すべての投稿を表示
ラベル 累積和 の投稿を表示しています。 すべての投稿を表示

2014 TCO Celebrity Match DIV1 Easy - AnEasyProblem

2014 TCO Celebrity Match DIV1 Easy - AnEasyProblem

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13527&rd=16191

・関数F(h,r)が与えられる。その要素は{1,2,3,...h-1,h,h-1...r+1,r}となる。
 (例)F(3,2)={1,2,3,2}
・関数Fの和があらかじめわかっているとき、その和を構成できる関数Fのうち
 最も少ない要素数を求める。
 そのようなFがない場合は−1を返す。

解き方


和の最大が10^12であるため、n*(n+1)/2<=10^12から
nは最大でも10^6程度なので全探索できそう。

まず1から単調増加で和を計算していき、そのような和が構成できれば
それは最小要素なので答えになる。

そのような最小要素がなければ、途中で折り返す要素を計算する。

この場合最悪ケースで10^12になってしまうので、工夫が必要。

このとき、折り返し分の要素は最大のnからn-1,n-2・・・の和のいずれかであるので
あらかじめ累積和を計算しておき、二分探索することで
計算量を20*10^6に収めることができる。

コード


long long dp[1500000];

class AnEasyProblem {

public: int solve(long long sum) {
long long cur=0;
int n=0;
while(cur+n+1<=sum){
n++;
cur+=n;
}
if(cur==sum)return n;

dp[0]=0;
for(int i=1;i<=n;i++)dp[i]=dp[i-1]+i;

for(int x=n;x>=1;x--){
if(dp[x-1]*2+x<sum)break;
long long tmp=dp[x-1]-(sum-dp[x]);
int m = (lower_bound(dp,dp+n,tmp)) - dp ;
if(dp[m]==tmp)return (x-1)-m+x;
}

return -1;
}

};

SRM 610 DIV1 Easy - TheMatrix (×○)

SRM 610 DIV1 Easy - TheMatrix (×○)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13035&rd=15843

・白と黒で表わされる2次元のボードが与えられる。
・ここから任意の長方形を選び、それが交互に白と黒が現れる模様であればそれはチェスボードと呼ぶことができる。
・そのうち、最大の大きさとなるチェスボードの面積を求める。

解き方


・ボードの大きさは最大100*100
・ボードの長方形の選び方は10^8なのでギリギリそう。
・長方形を選んだときにそれがチェスボードとO(1)で判断できれば間に合うが・・・

→他の人のコードをみる

・あらかじめ各行について、どの長さまでチェスボードが成立するか事前計算しておく。
・長方形の左上の点のすべてについて、一つずつ下に拡大していき
 左の点がチェスボードが続けば、その下の行の続くチェスボードの長さとの最小をとれば
 そのときの最大のチェスボードを計算することができる。

・反省:ボードの計算方法をシミュレーションするのが不足していた。もっと紙に書くのが必要。

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

int d[101][101];

class TheMatrix {

public: int MaxArea(vector<string> board) {
int h=board.size(),w=board[0].size();
memset(d,0,sizeof(d));

FORE(i,0,h)FORE(j,0,w){
int len=1;
FORE(k,j+1,w){
if(board[i][k]!=board[i][k-1])len++;
else break;
}
d[i][j]=len;
}

int ret=0;
FORE(j,0,w)FORE(i,0,h){
int len=d[i][j];
FORE(k,i,h){
if(k!=i && board[k-1][j]==board[k][j])break;
len=min(len,d[k][j]);
ret=max(ret,(k-i+1)*len);
}
}

return ret;
}

};

SRM 624 DIV1 Easy - BuildingHeights (×)

SRM 624 DIV1 Easy - BuildingHeights (×)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13211&rd=15857

・様々な高さを持つ建物が与えられる。
・建物の高さを1変えるのにコストが1かかる。
・同じ建物がm個必ずあるようにしたい。
・建物の数をnとしたとき、mは1~nすべての値としてそれぞれの最小コストのXORを求める。

解き方


・mを1~nそれぞれについて調べることとし、各建物の長さについて答えを求める。
・求め方として2分探索?でも最小値を求めるので使えなさそう。
・全探索では4000*4000*4000かかりそう。

→他の人のコードをみてみる

・mを固定した時、どの長さにするかは各建物の元々の長さにすればよい、、ことを単純ながら見落としてしまった。
・あとは各建物の長さに固定した時のコスト計算をO(1)とするために、累積和をとっておけばよい。

・反省:最適解探索の検討がまだまだ足りない。

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()


class BuildingHeights {

public:

int minimum(vector<int> heights) {
int n=heights.size();
sort(all(heights));

int sum[n+1];
sum[0]=0;
FORE(i,1,n+1)sum[i]=sum[i-1]+heights[i-1];

int ret=0;
FORE(i,1,n+1){
int cur=1e+9;
FORE(j,i-1,n)cur=min(cur,heights[j]*i-(sum[j+1]-sum[j+1-i]));
ret^=cur;
}

return ret;
}

};

SRM 636 DIV1 Easy - ChocolateDividingEasy (×)

SRM 636 DIV1 Easy - ChocolateDividingEasy (×)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13497&rd=16079

1*1のセルが組み合わされた長方形のチョコレートケーキがある。
各セルごとにおいしさの値が与えられる。

このケーキを横に2つ、縦に2つ切って9つにわける。
このとき、分けたかけらのうちの最小のおいしさの値が最大となる値を求める。


解き方


・計算量の見積もりを誤ってしまった。
・縦に2つ、横に2つなので50C2*50C2=1.5*10^6ぐらい。
・分けたときの各かけらの値を累積和の差として求めれば間に合う。

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

int b[100][100];
int f[100][100];

class ChocolateDividingEasy {

public: int findBest(vector<string> chocolate) {
int n=chocolate.size();
int m=chocolate[0].size();


FORE(i,1,n+1)FORE(j,1,m+1)b[i][j]=chocolate[i-1][j-1]-'0';
FORE(i,0,n+1)FORE(j,0,m+1){
if(i==0||j==0)f[i][j]=0;
else{
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+b[i][j];
}
}

int ret=0;
FORE(ia,1,n)FORE(ib,ia+1,n)FORE(ja,1,m)FORE(jb,ja+1,m){
int is[4],js[4];
is[0]=0,is[1]=ia,is[2]=ib,is[3]=n;
js[0]=0,js[1]=ja,js[2]=jb,js[3]=m;
int tmp=1e+9;
FORE(i,1,4)FORE(j,1,4){
tmp=min(tmp,f[is[i]][js[j]]-f[is[i]][js[j-1]]-f[is[i-1]][js[j]]+f[is[i-1]][js[j-1]]);
}
ret=max(ret,tmp);
}

return ret;
}

};