TCO2011 Qual1-A 500pt: FoxListeningToMusic
問題概要
正整数列X(長さN<50, x[i]
解法
dp[i] = {iが端点になっている確率}とすれば、これはO(T*N)で求められる。その後、i+X[i]>=Tとなる確率を足し上げていけばよい。全体の計算量はO(T*N)。
感想
dp[i][k] = {iが棒kの右端になっている確率}としてO(T*N^2)だとギリギリTLEする。最大ケースは{1..1},80000だと思っていたけど(これならTCのサーバー上で通る)、多分キャッシュの関係で{1..1,80000},80000の方が重い。
追記:遅いのはキャッシュのせいではなく非正規化数のせいだった。
vector <double> getProbabilities(vector <int> length, int T) { int N = length.size(); double p = 1.0/N; vector<double> dp(T+2,0); dp[0] = 1.0; for(int t=0; t<=T; t++){ for(int i=0; i<N; i++){ dp[min(T+1, t+length[i])] += dp[t]*p; } } vector<double> ret(N,0.0); for(int t=0; t<=T; t++){ for(int i=0; i<N; i++)if(t+length[i] >= T+1){ ret[i] += dp[t]*p; } } return ret; }
TLE解
class FoxListeningToMusic { public: vector <double> getProbabilities(vector <int> length, int T) { int N = length.size(); double p = 1.0/N; vector< vector<double> > dp(T+2, vector<double>(N,0.0)); dp[0][0] = 1.0; for(int i=0; i<=T; i++){ for(int j=0; j<N; j++){ for(int k=0; k<N; k++){ int nt = min(T+1, i+length[k]); dp[nt][k] += dp[i][j]*p; } } } return dp[T+1]; }