Loading...
6/10/2025
残す値の個数の最大値がもとまれば、消す値の個数の最小値がわかるので、前者を考えることにする。
この問題において、数列の値の総和と所持しているお金の合計は一定である。つまり、目標の数列があって、であるならば数列Bを構成可能であると言える。また、「長さのいい数列であって、総和を最小とするような数列は何か?」を考えると、これは素数を小さい方から個並べた列である1。
よって、以下の問題を高速に解くことができれば元の問題が解ける。なお、は降順にソートされている2としは素数を小さい方から並べた数列であるとする。
以下を満たすの最大値を求めよ。
ももすでに決まっているので前から順に判定しても良いし、条件には単調性があるので二分探索を用いることもできる。
vll primes=Eratosthenes(1e7); void solve() { int n; cin >> n; auto a=i64_vec_IN(n); sort(all(a)); reverse(all(a)); ll ok = 1; ll ng = n+1; while(abs(ok-ng)>1) { ll mid = (ok+ng)>>1; ll sa=0; ll sp=0; rep(i,mid){ sa+=a[i]; sp+=primes[i]; } if(sa>=sp)ok=mid; else ng=mid; } cout << n-ok << ' '; } int main() { cin.tie(0); ios::sync_with_stdio(false); int t=1; cin >> t; while(t--)solve(); }
エラトステネスの篩を前計算し、を「番目の素数」とする。
ソートがボトルネックとなり、時間となる。