Codeforces Round #16 (Div2 only)
今回からDiv2 onlyのコンテストにも(レーティング変動なしで)レーティング1500以上の人も参加できるようになったみたい。
Result
27位(Div1の人含) rankalee 5AC penalty272
00:03 00:21(2WA) 00:29 01:11(1WA) 01:08(1TLE)
A. Flag
問題
nxmマスの色のついた小正方形からなる旗が、ストライプであるかどうかを判定せよ。
ただし、ストライプであるとは、
- 同じ行にあるマスの色は全て等しい
- となりあう列の縞の色は全て異なる
という条件を満たすものをいう。
試行錯誤
条件にしたがって実装。
送信。AC.
ソースコード
void run() { int h,w; cin>>h>>w; vs str(h); bool ok=1; rep(i,h) { cin>>str[i]; rp(j,str[i])if(str[i][j]!=str[i][0])ok=0; } for(int i=1;i<h-1;i++)if(str[i-1][0]==str[i][0]||str[i+1][0]==str[i][0])ok=0; cout<<(ok?"YES":"NO")<<endl; }
B. Burglar and Matches
問題
m種類のマッチ箱の入ったコンテナがある。
i番目のマッチ箱がa[i]個あり、a[i]個のそれぞれに等しくb[i]本のマッチ棒が入っている。
今、n個のマッチ箱の入るリュックサックにn個のマッチ箱を選んで入れたい。
このときリュックに入る最大のマッチの本数を求めよ。
マッチ箱の中のマッチを移し変えてはならない。
n≦2*10^8,
1≦m≦20,
1≦ai≦10^8,
1≦bi≦10である
試行錯誤
ナップサック問題かー(←誤読)
aが大きくてmが小さいから全通り試せって問題だな!
ビット使って書いた。サンプル合わない。
あ、1つの箱に何個も入れる場合あるのか。じゃあ深さ優先探索に書き換え。
あれ?サンプル合わないぞ。問題を読み直す。
あ、ああ貪欲につめるだけか……orz
送信。WA.
あれ?ひょっとしてlong longいる?訂正。送信WA.
なんぞ。あ、ループの回数でmとnミスってる箇所あるorz
もう!!!!UAPCの失敗から学べよ!!!!
送信。AC.
ソースコード
int n,m; pi p[20]; void run() { cin>>n>>m; rep(i,m) { int a,b; cin>>a>>b; p[i]=mp(b,a); } sort(p,p+m,greater<pi>()); ll ans=0; rep(i,m) { ll t=min(p[i].second,n); //注:llは必要ない ans+=t*p[i].first; n-=t; } cout<<ans<<endl; }
C. Monitor
貪欲法のBでハマるとか酷いw
問題
縦a,横bのパネルを切って縦x:横yのパネルで、
縦横の辺の長さが整数かつ、面積が最大になるようなものを作りたい。
そのようなパネルの縦の長さと横の長さを求めよ。不可能なときは0 0を出力せよ。
1≦a,b,x,y≦2*10^9である。
試行錯誤
えーと?不定方程式を解くのかな?でも10^9だからループとかしてると死ぬ。
素因数分解……
あ、いや縦横の辺の長さをmxとmyとしてmx≦aかつmy≦bな最大のmを求めればいいだけか。(x,yはあらかじめgcdで割る)
これで求めると切り出せない場合もm=0になって含まれる。
送信。AC.
ソースコード
void run() { int a,b,x,y; cin>>a>>b>>x>>y; int g=__gcd(x,y); x/=g,y/=g; int m=min(a/x,b/y); cout<<m*x<<" "<<m*y<<endl; }
D. Logging
なんか今回Div2 onlyにしても問題簡単?
問題
[date:time]: messageの形でログが与えられる。
date:timeは12時間形式で12:13 a.mのように指定される。
ログが時間順に並んだ後で日付を削除されている時、全てのログを出力するには最短で何日間かかるかを求めよ。
1分以内に10個より多くのログは出力されない。
試行錯誤
まず12時間形式の時間を0:00からの経過分で表す。
(12%h)*60+mと。
で、時間が逆転してたり、time[i]>time[i-1]の連続数を数えて10以上だったら日付をめくればいいのかな(←間違いtime[i]==time[i-1]の連続数を数えるべき)
書いた。送信。WA.なんぞー。
よくわからないので次の問題解いてからにしよう。
E. Fish
あ、iwi先生が40分かからずに全部の問題解いてる。すげーw
問題
湖にn匹の魚が棲んでいる。
一日の終わりに湖の中の魚のうちどれか二匹がランダムに選ばれ、
選ばれた魚をiとjとすれば、確率pijで1匹目が2匹目を食べ、
確率1-pijで2匹目が1匹目を食べる。
これが湖に二匹以上魚がいる限り続けられるとき、それぞれの魚が生き残る確率を求めよ。
n≦18である。
試行錯誤
nが18だからビットDPすればよさげ。
計算量はn^3*2^nくらいだから間に合いそう。
書いた。サンプル合わない。あぁ魚が1匹になるのはn日目じゃなくてn-1日目かw
訂正。送信。
TLE.
あれ、これ確率が0になるような配列もわざわざ呼び出すとダメ?
うーん。ビットを選ぶ部分をnext_permutation使って書き直そう。
訂正。一発でサンプルもあった。
送信。AC.
ソースコード
int n; double p[18][18]; double dp[20][1<<18]; void run() { cin>>n; rep(i,n)rep(j,n)cin>>p[i][j]; rep(i,20)fill_n(dp[i],1<<n,0); dp[0][(1<<n)-1]=1; for(int i=1;i<n;i++) { int tmp[n]; rep(j,n)tmp[j]=j>=i-1; do { int bit=0; rep(j,n)bit*=2,bit+=tmp[j]; double meet=(n-i+1)*(n-i)/2.0; rep(j,n)if(bit&1<<j)rep(k,j)if(bit&1<<k) { dp[i][bit^1<<j]+=dp[i-1][bit]*p[k][j]/meet; dp[i][bit^1<<k]+=dp[i-1][bit]*p[j][k]/meet; } }while(next_permutation(tmp,tmp+n)); } rep(i,n)cout<<dp[n-1][1<<i]<<(i==n-1?"\n":" "); }
E(再)
あー、1分間に10個のログまで、だからtime[i]==time[i-1]のときに連続を数えるのか。
訂正。
送信。AC.
ソースコード
void run() { int n; cin>>n; cin.ignore(); int time[100]; rep(i,n) { string s,a,b; getline(cin,s); a=s.substr(1,2); b=s.substr(4,2); int h,m; stringstream(a)>>h; stringstream(b)>>m; time[i]=(h%12)*60+m; if(s[7]=='p')time[i]+=720; } int ans=1,suc=0; for(int i=1;i<n;i++) { if(time[i]<time[i-1]) { suc=1; ans++; } else if(time[i]>time[i-1]) { suc=1; }else { suc++; if(suc>10) { suc=1; ans++; } } } cout<<ans<<endl; }
すごくアドホックに直した感が出てるw