Loading...
4/25/2025
合計がとなる正整数の選び方であって、がo
であるような全てのについて、選んだ数のいくつかを取って合計したときににできるように、数字を選びたい。最小で何個選ぶ必要があるか?
まず、答えの上界を考える。二進数表記の気持ちになると、1, 2, 4, 8, ...というように2の累乗点のセットを用意してあげれば、条件を達成することができる。であり、であるため、多くとも7問用意すれば条件を満たすことが可能である。
よって、少ない方から順に、問用意して条件を達成できるか?を判定していけば良い。和がである、という制約に注意すると(適当な個を用意すると残りの一つは勝手に決まるので)用意する問題セットとしてあり得る組は通りとなり、最悪で1ケース辺り通りを計算することによってこの問題が解くことができる。
実際には最大で100ケースありこのまま解くには定数倍が厳しいが、
o
の位置を事前に列挙しておく
などの定数倍高速化を行うことでこの問題が解ける。提出コードstring s; vector<int> o_positions; bool dfs(int idx, int left, int last, bitset<101>& bs) { vector<int> updated; if(idx==0) { per(j, s.size()-left) { if(!bs[j] || bs[left+j]) continue; bs[left+j] = true; updated.push_back(left+j); } bool res = true; for(auto i: o_positions) res = res && bs[i]; for(auto pos : updated) { bs[pos] = false; } return res; } bool res = false; rep2(i,last,left+1) { if(left-i<i) break; per(j, s.size() - i) { if(!bs[j] || bs[i+j]) continue; bs[i+j] = true; updated.push_back(i+j); } res = dfs(idx-1, left-i, i, bs); if(res) break; for(auto pos : updated) { bs[pos] = false; } updated.clear(); } return res; } void solve(int n) { cin >> s; o_positions.clear(); rep(i, s.size()) if(s[i]=='o') o_positions.push_back(i); bitset<101> bs; bs[0] = true; rep(i,6){ auto ret = dfs(i, n, 1, bs); if(ret) { cout << i+1 << ' '; return; } } cout << "7 "; } int main() { cin.tie(0); ios::sync_with_stdio(false); int n; cin >> n; while(n) { solve(n); cin >> n; } }