Loading...
4/4/2025
お久しぶりです。オンサイトやら何やらが被りに被って更新が途切れていましたが、ちまちまと更新していきます。競プロ以外の、シンプルな日記とかもたまには更新したいと思っていますが、まぁそのうち...
2kgのcloudberryから色々すると3kgのジャムが完成するので、3kgのジャムをn個用意するのに必要なcloudberryはです。
void solve() { int n; cin>>n; cout<<2*n<<' '; } int main() { cin.tie(0); ios::sync_with_stdio(false); int t; cin >> t; while(t--)solve(); }
難しいですね。初め、の組を数え上げるものだと思っており「どう考えても64bitに収まらなくないですか?」と叫んでいました。が、よく見るとこれを数えるんですね、なるほど。
これは真ん中を圧縮してRがどこになるかをを2つ並べた配列で累積和を取って二分探索することで右端がどこになるかを持ってやればいいですね~と言いながら適当に書くとWAが帰ってきます。あの?
一旦C, Dを通してから戻ってくると、明らかに二分探索の下界を間違えているので直して提出すると通ります。
void solve() { ll n, k, x;cin>>n>>k>>x; vll a(2*n);rep(i,n)cin>>a[i], a[n+i]=a[i]; vll csum(2*n+1,0); rep(i,2*n)csum[i+1]=csum[i]+a[i]; ll sum = csum[n] - csum[0]; vll r(n); rep(i,n){ ll full = 0; ll left = x; if(x>=sum){ full = x/sum; left = x%sum; } ll ok = 2*n+1; ll ng = i-1; while(abs(ok-ng)>1){ ll mid = (ok+ng)/2; if(csum[mid]-csum[i]>=left) ok = mid; else ng = mid; } r[i]=full*n+ok-1; } ll ans = 0; rep(i,n){ if(r[i]>=n*k) continue; ll t = r[i]/n; ans+=(k-t); } cout << ans << ' '; } int main() { cin.tie(0); ios::sync_with_stdio(false); int t; cin >> t; while(t--)solve(); }
ECRはICPCルール(のはず)なので、ペナとACが遅れたぶんを合わせて+100ほど。流石に勿体ないです。
操作をした結果、「値を置き換える必要があるもの」を考えてあげると、どうも残っているもので閉路をなしているものは置き換える必要はなくて、そうでないものは置き換える必要がありそうです。適当にUnionFindでチェックしてあげればよいですね。
void solve() { int n; cin >> n; vll p(n); rep(i,n)cin>>p[i],p[i]--; vll q(n); rep(i,n)cin>>q[i],q[i]--; dsu uf(n); rep(i,n) { uf.merge(p[i], p[p[i]]); } vector<bool> seen(n, false); vll ans(n); ll cur=0; rep(i,n){ if(!seen[uf.leader(p[q[i]])]) { cur+=uf.size(p[q[i]]); seen[uf.leader(p[q[i]])]=true; } ans[i]=cur; } rep(i,n)cout<<ans[i]<<((i+1==n)?' ':' '); } int main() { cin.tie(0); ios::sync_with_stdio(false); int t; cin >> t; while(t--)solve(); }
...ん?これどこかで見覚えがありますね?
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Dこれの気持ちになってしまったので気合でメモ化再帰で980ms <a href="https://t.co/KmRSxQVNDb">https://t.co/KmRSxQVNDb</a></p>— ardririy❄* (@ardririy) <a href="https://twitter.com/ardririy/status/1907836755572826457?ref_src=twsrc%5Etfw">April 3, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ということで、メモ化再帰でやると通ります。あとから指摘されましたが計算量保証はできません。とりあえず定数倍の良いです。テストケースが弱いのでOK!
using mint = ModInt<998244353>; mint fact[300003]; const int n = 26; vector<int> c(n); mint choose(int n, int k) { return fact[n] / (fact[k] * fact[n-k]); } map<pair<int, int>, mint> memo; mint rec(int i, int e, int o) { if(i==n) { if(e==0&&o==0){ return 1; } else { return 0; } } if(e>o) swap(e, o); P p = {e,o}; if(memo.find(p)!=memo.end()){ return memo[p]; } if(c[i]==0){ return rec(i+1, e, o); } mint res = 0; if(e>=c[i]) { res = res + choose(e, c[i]) * rec(i+1, e-c[i], o); } if(o>=c[i]){ res = res + choose(o, c[i]) * rec(i+1, e, o-c[i]); } return memo[p]=res; } void solve() { int sum = 0; memo.clear(); rep(i,n)cin>>c[i], sum+=c[i]; int even = sum/2; int odd = sum-even; cout << rec(0, even, odd).value << ' '; } int main() { cin.tie(0); ios::sync_with_stdio(false); int t; cin >> t; fact[0] = 1; rep(i,300001){ fact[i+1] = fact[i]*(i+1); } while(t--)solve(); }