SRM-426 250pt: ShufflingMachine
keyword
期待値 Greedy C++
問題概要
数列0,1,...,N-1(N<50)がある。これが1~S(<100)回(確率は一様)置換される。置換が終わった後、i_1, i_2, ..., i_p番目の数字が自分に割り振られる。最初に数列を並び替えることによって0,1,...,K-1が自分の手元に来るようにしたい。最善を尽くしたとき、いくつ得ることができるの期待値を求める問題。
解法
期待値の問題ではお馴染みの線形性を使う。置換をS回シミュレートして、数字jがi_1, i_2, … , i_p番目に出てくる回数をカウントする。後は出現頻度の高いものを上からK個とってくれば良い。
感想
期待値の問題は、線形性60%、DP(漸化式)30%、(連立)方程式5%、その他(2分探索とか)5%位な印象がある。問題文解読するのに時間をかけすぎた。
int cnts[110][110]; int as[110]; double stackDeck(vector <int> shuffle, int maxShuffles, vector <int> cardsReceived, int K) { double ret = 0.0; int i,j,N=SZ(shuffle); REP(i,110)REP(j,110) cnts[i][j] = 0; vector<int> cur(N), next(N); REP(i,N) cur[i] = i; FOR(i,1,maxShuffles+1){ REP(j,N){ next[shuffle[j]] = cur[j]; } cur = next; REP(j,N){ cnts[j][cur[j]]++; } } REP(i,N){ as[i] = 0; REP(j,SZ(cardsReceived)){ as[i] += cnts[cardsReceived[j]][i]; } } REP(i,N)cout<<as[i]<<", ";cout<<endl; REP(i,K){ int *p = max_element(as,as+N); ret += *p; *p = 0; } return ret/maxShuffles; }