ラベル 確率 の投稿を表示しています。 すべての投稿を表示
ラベル 確率 の投稿を表示しています。 すべての投稿を表示

SRM 650 DIV1 Easy - TaroFillingAStringDiv1 (○)

SRM 650 DIV1 Easy - TaroFillingAStringDiv1 (○)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13669&rd=16314

・AとBから成る文字列を作りたい。
・ただし、i番目の文字はAかBか決まっており、最初にその情報が与えられる。
・また、できるだけAとBが連続しているようにはしたくない。
・上記の情報が与えられるとき、できるだけAとBが連続しないような文字列の場合の数を
 求める。

解き方


・まず、できるだけAとBが連続しないような文字列を求める。
 与えられた情報の位置でソートし、それぞれの間について考える。
 このとき、それぞれのスペースの数+両端のAかBの一致か不一致かによって
 AとBがひとつも連続しないか、そうでないかがわかる。

・次に、そのような場合の数を求める。
・AとBが連続しないようなケースの場合は1通りしか置き方はない。
・AとBが連続するようなケースは、スペースの数だけ場合の数が存在する。

・最後にそれぞれのスペースについての積をとってあげれば答えになる。

コード


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 MOD=1000000007;

class TaroFillingAStringDiv1 {

public: int getNumber(int N, vector<int> position, string value) {
int n=position.size();
vector<pair<int,char> > p;
FORE(i,0,n)p.push_back(make_pair(position[i],value[i]));
sort(all(p));

long long ret=1LL;
FORE(i,0,n-1){
int cur=p[i+1].first-p[i].first;
if((cur+(p[i].second!=p[i+1].second))%2)ret=(ret*cur)%MOD;
}
return ret;
}

};

SRM 626 DIV1 Easy - FixedDiceGameDiv1 (×)

SRM 626 DIV1 Easy - FixedDiceGameDiv1 (×)

問題


http://community.topcoder.com/stat?c=problem_statement&pm=13239&rd=15859

・AliceとBobでゲームを行う。
・Aliceはa個b面あるサイコロを投げ、Bobはc個d面あるサイコロを投げる。
・b面あるサイコロは1~bの数字が書かれており、d面あるサイコロは1~dの数字が書かれている。
・Aliceが勝った時、出た目の期待値を求める。
・Aliceが勝つケースがないときは-1を返す。

解き方


・まずAliceが勝つかどうか判定する。
・Bobの一番小さい数はcであるので、c+1以上の面が出るときに勝つことができる。
・次にAliceの勝つ面について、どれだけの確率があるか計算する。
・dpを用いればできそう。
・現在までに使ったサイコロの数、現在までの合計のスコアを持つdpを作れば
 場合の数は計算できる。
・確率として、勝つ面が出た時のすべての場合の数の和を取り、最後に割ってあげる。
・サンプルはすべて通った。

→System Failed

・Aliceだけの面をみていたが、Bobの面も見る必要がある。
・つまり、Aliceの勝つ数についての場合の数*Bobがそれに負けるときの場合の数を足してあげ、
 その和を全てとり最後に割ってあげる必要がある。

・反省:確率の問題に弱い・・・。基礎が足りないのを実感。

コード


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 FixedDiceGameDiv1 {

public: double getExpectation(int a, int b, int c, int d) {
double dp1[a+1][2501],dp2[c+1][2501];
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));

dp1[0][0]=dp2[0][0]=1;

FORE(i,0,a)FORE(j,0,2501)FORE(k,1,b+1)if(j+k<=a*b)dp1[i+1][j+k]+=dp1[i][j];
FORE(i,0,c)FORE(j,0,2501)FORE(k,1,d+1)if(j+k<=c*d)dp2[i+1][j+k]+=dp2[i][j];

double ret=0.0,sum=0.0;
FORE(i,c+1,a*b+1){
double p=0.0;
FORE(j,0,i)p+=dp2[c][j];
ret+=i*dp1[a][i]*p;
sum+=dp1[a][i]*p;
}

return ret ? ret/sum : -1;
}

};

SRM 156 DIV1 Easy - BombSweeper

SRM 156 DIV1 Easy - BombSweeper

問題


http://community.topcoder.com/stat?c=problem_statement&pm=1778&rd=4585

マリンスイーパーを解く。

最初に好きな場所を選ぶ。
①そこにボムがあれば負け
②ボムがなくても周りにボムがあれば違うセルを選ぶ
③ボムがなくて、かつ周りにボムがなければ勝ち

このとき、勝率を求める。

解き方


ボムがなくて周りにボムがある場合は違うセルを選ぶ、つまりノーカウントとなるので、
①と③の数のみ調べて100*③/(①+③)が答えになる。

コード


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 BombSweeper {

public: double winPercentage(vector<string> board) {
int w=board[0].size(),h=board.size();
int ret=0,bomb=0;

FORE(i,0,h){
FORE(j,0,w){
int valid=1;
FORE(x,max(i-1,0),min(i+2,h))FORE(y,max(j-1,0),min(j+2,w))if(board[x][y]=='B')valid=0;
if(valid)ret++;
if(board[i][j]=='B')bomb++;
}
}
return 100.0*ret/(double)(bomb+ret);
}

};

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 BombSweeper {

public: double winPercentage(vector<string> board) {
int h=board.size(),w=board[0].size();
int win=0,lose=0;

FORE(i,0,h)FORE(j,0,w){
if(board[i][j]=='B')lose++;
else{
int valid=1;
FORE(k,i-1,i+2)FORE(l,j-1,j+2){
if(0<=k && k<h && 0<=l && l<w && board[k][l]=='B')valid=0;
}
win+=valid;
}
}

return (double)win/(win+lose)*100.0;
}

};

SRM 174 DIV1 Easy - BirthdayOdds

SRM 174 DIV1 Easy - BirthdayOdds

問題


http://community.topcoder.com/stat?c=problem_statement&pm=1848&rd=4675

何人かのグループを考えた時、ある割合で同じ誕生日の人が存在する。

同じ誕生日の人がいる確率が与えられ、また誕生日となりうる日数が与えられた時、
何人の人がいれば与えられた確率以上で同じ誕生日の人が存在するかを求める。

解き方


日数をDとすると、D/D*(D-1)/D・・・と計算していき
この値が100-与えられた確率以下になるときの人数を答えればよい。

コード


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 BirthdayOdds {

public: int minPeople(int minOdds, int daysInYear) {

double p=1.0;
FORE(i,1,daysInYear){
p*=(double)(daysInYear-i)/daysInYear;
if(p*100<=100-minOdds)return i+1;
}

return daysInYear+1;
}

};

SRM 293 DIV1 Easy - ScrabbleBet

SRM 293 DIV1 Easy - ScrabbleBet

問題


http://community.topcoder.com/stat?c=problem_statement&pm=6116&rd=9814

1セットあたりのゲーム回数が与えられ、それを指定回数分のセット数行う。
1ゲームにたいして勝つ確率が与えられ、そのセット数で勝つために必要な勝ちゲーム数が与えられる。

このとき、少なくとも1つのセットで勝つことのできる確率を求める。

解き方


問題文の理解に少し時間がかかった。

1セットあたりに負ける確率さえ計算できれば、答えは1-負ける確率^セット数で求められる。

1セットあたりに負ける確率の計算に順列を使ってもよいが、
ゲーム数は20なので全探索してもたかだか10^6程度なので間に合う。

コード


class ScrabbleBet {

public: double estimate(int trials, int games, int winsNeeded, int winChance) {
double loses=0.0;
double p=winChance/100.0;

for(int i=0;i<(1<<games);i++){
int x=0;
for(int j=0;j<20;j++)if(i&(1<<j))x++;
if(x<winsNeeded)loses+=pow(p,x)*pow(1.0-p,games-x);
}

return 1.0-pow(loses,trials);
}

};

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 ScrabbleBet {

public:

double C(int a,int b){
double ret=1.0;
FORE(i,0,b)ret*=(double)(a-i)/(1+i);
return ret;
}

double estimate(int trials, int games, int winsNeeded, int winChance) {
double p=0.0;
double winp=winChance/100.0;

FORE(i,winsNeeded,games+1){
p+=C(games,i)*pow(winp,i)*pow(1.0-winp,games-i);
}

return 1.0-pow(1.0-p,trials);
}

};