Codeforces Round 1049 (Div. 2)

A. Shift Sort

发现左移或右移等价于交换两个位置的数

所以答案即为前 \(cnt0\) 个数中有几个 \(1\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
	int n;
    cin>>n;

    vector<int> a(n+1);
    int cnt=0;
    for(int i=1;i<=n;i++){
        char ch;
        cin>>ch;
        a[i]=(ch=='1');
        if(a[i]==0) cnt++;
    }

    int ans=0;
    for(int i=1;i<=cnt;i++){
        if(a[i]) ans++;
    }

    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

B. Another Divisibility Problem

\(y=2*x\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
	int n;
    cin>>n;
    cout<<2*n<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

C. Ultimate Value

后手一定直接结束游戏

所以只需要计算第一次先手能得到的最大贡献

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
	int n;
    cin>>n;

    vector<int> a(n+1);
    int sum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(i&1) sum+=a[i];
        else sum-=a[i];
    }

    int t=0;

    //l,r奇偶性相同
    if(n&1) t=n-1;
    else t=n-2;

    vector<int> l(n+1),preoddl(n+1,-inf),preevenl(n+1,-inf);
    for(int i=1;i<=n;i++){
        if(i&1) l[i]=-i-2*a[i];
        else l[i]=-i+2*a[i];

        preoddl[i]=preoddl[i-1];
        preevenl[i]=preevenl[i-1];

        if(i&1) preoddl[i]=max(preoddl[i],l[i]);
        else preevenl[i]=max(preevenl[i],l[i]);
    }

    for(int i=2;i<=n;i++){
        if(i&1){
            t=max(t,preevenl[i-1]+i-2*a[i]);
            // cout<<preevenl[i-1]<<" "<<i-2*a[i]<<" ";
        }
        else{
            t=max(t,preoddl[i-1]+i+2*a[i]);
            // if(i==6) cout<<preoddl[i-1]<<" "<<i-2*a[i]<<" ";
        }
    }

    // cout<<endl;
    cout<<sum+t<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

D. A Cruel Segment's Thesis

\(n\) 是偶数时,可以直接两两配对计算出答案

此时需要 \(n/2\)\(-y\),和 \(n/2\)\(r\)

如果 \(n\) 是奇数,则需要在偶数的基础上,枚举单独拎出来哪一个线段,对答案的副贡献最小

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
	int n;
    cin>>n;

    vector<int> r(n+1),l(n+1);
    vector<pii> a(n+1);
    int ans=0;

    for(int i=1;i<=n;i++){
        cin>>l[i]>>r[i];
        ans+=(r[i]-l[i]);
        ans+=r[i];
        a[i]={r[i]+l[i],r[i]};
    }
    vector<int> st(n+1);//st[i]:i是否给L贡献 

    sort(a.begin()+1,a.end());

    for(int i=1;i<=n/2;i++){
        ans-=a[i].first;
        st[i]=1;
    }

    if(n&1){
        //如果单独的段,在之前贡献的是r,则只需要把这个r删掉即可
        int cost=inf;
        for(int i=n/2+1;i<=n;i++){
            cost=min(cost,a[i].second);
        }

        //如果单独的段,之前贡献的是l,则需要加上这个l
        //再从贡献r的里面找一个改为贡献l,cost是-r-l
        for(int i=1;i<=n/2;i++){
            cost=min(cost,(-a[i].first+a[i].second)+a[n/2+1].first);
        }

        cout<<ans-cost<<endl;
    }
    else{//偶数
        cout<<ans<<endl;
    }
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

E1. Prime Gaming (Easy Version)

设状态 \(dp[i] [j] [k]\) 表示,当前轮到玩家 \(i\),还剩 \(j\) 堆石子,石子的状态是 \(k\)

\(i:(0/1)\)\(k:\) 如果第 \(x\) 堆有一个石子,则 \(k\) 的第 \(x\) 位为 \(0\),否则为 \(1\)

\(dp[i] [j] [k]\) 可以从 \(dp[-] [j-1] [-]\) 转移得到

点击查看代码
#include<bits/stdc++.h>
// #define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 1e9+7;

/*支持define int long long 的自动取模类*/
template<const int T>
struct ModInt {
    const static int mod = T;
    int x;
    ModInt(signed x = 0) : x(x % mod) {}
    ModInt(long long x) : x((int)x % mod) {} 
    int val() { return x; }
    ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
    ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
    ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
    ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
    bool operator == (const ModInt &a) const { return x == a.x; };
    bool operator != (const ModInt &a) const { return x != a.x; };
    void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }
    void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }
    void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
    void operator /= (const ModInt &a) { *this = *this / a; }
    friend ModInt operator + (int y, const ModInt &a){ int x0 = y + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
    friend ModInt operator - (int y, const ModInt &a){ int x0 = y - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
    friend ModInt operator * (int y, const ModInt &a){ return ModInt(1LL * y * a.x % mod);}
    friend ModInt operator / (int y, const ModInt &a){ return ModInt(y) / a;}
    friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x;}
    friend istream &operator>>(istream &is, ModInt &t){return is >> t.x;}

    ModInt pow(int64_t n) const {
        ModInt res(1), mul(x);
        while(n){
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    
    ModInt inv() const {
        int a = x, b = mod, u = 1, v = 0;
        while (b) {
            int t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        if (u < 0) u += mod;
        return u;
    }
    
};
using mint = ModInt<mod>;

void solve(){
	int n,m,k;
    cin>>n>>m>>k;

    vector<int> good(k);
    for(int i=0;i<k;i++){
        cin>>good[i];
    }

    if(m==1){
        cout<<1<<endl;
        return;
    }

    //f[i][j][k]
    //i:0-ALice/1-Bob 
    //轮到i操作时,还剩j个数,状态为k的答案
    vector<vector<vector<int>>> f(2,vector<vector<int>>(n+1,vector<int>(1<<n)));

    //状态mask移除第k位后的结果
    auto get=[&](int mask,int pos)->int {
        int up=mask>>(pos+1);
        int low=mask&((1<<pos)-1);
        return (up<<pos)+low;
    };

    //还有多少位数
    for(int i=1;i<=n;i++){
        if(i==1){
            f[0][i][1]=1;
            f[0][i][0]=0;
            f[1][i][1]=1;
            f[1][i][0]=0;
        }
        else{
            for(int k=0;k<(1<<i);k++){
                int ansA=0;//只要可以转移到一个1,ansA就是1
                int ansB=1;//只要可以转移到一个0,ansB就是0

                for(auto pos:good){
                    if(pos>i) continue;
                    int mask=get(k,pos-1);
                    ansA|=f[1][i-1][mask];
                    ansB&=f[0][i-1][mask];
                }

                f[0][i][k]=ansA;
                f[1][i][k]=ansB;
            }
        }
    }

    mint ans=0;

    for(int i=0;i<(1<<n);i++){
        ans+=(f[0][n][i]+1);
    }
    cout<<ans<<endl;

}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}
posted @ 2025-09-11 14:53  LYET  阅读(32)  评论(0)    收藏  举报