Codeforces Round 1059 (Div. 3)

 A. Beautiful Average

题目中n的范围很小,尝试暴力枚举,根据题目中给的公式,计算数组的前缀和,提高运行效率

查看代码
void solve(){
    int n;
    cin >> n;
    vector<int> a(n + 1, 0);
    for(int i = 1; i <= n; ++i) cin >> a[i];
    vector<int> res(n + 1,0);
    for(int i = 1; i <= n; ++i){
        res[i] = res[i - 1] + a[i];
    }

    int maxx = 0;
    for(int l = 0; l <= n; ++l){
        for(int r = l + 1; r <= n; ++r){
            if((res[r] - res[l]) / (r - l) > maxx){
                maxx = (res[r] - res[l]) / (r - l);
            }
        }
    }

    cout << maxx << endl;
    return ;
}

B. Beautiful String

查看代码
void solve(){
    int n;
    string s;
    cin >> n >> s;
    string p = s;
    reverse(p.begin(), p.end());
    if(p == s){
        cout << 0 << endl;
        cout <<  endl;
        return ;
    }

    vector<vector<int>> G(2);
    s = ' ' + s;
    for(int i = 1; i <= n; ++i){
        if(s[i] == '0')  G[0].emplace_back(i);
        else G[1].emplace_back(i);
    }

    if(!G[0].empty()){
        cout << G[0].size()  << endl;
        for(auto x : G[0]){
            cout << x << " ";
        }
        cout << endl;
        return  ;
    }else{
        cout << G[1].size()  << endl;
        for(auto x : G[1]){
            cout << x << " ";
        }
        cout << endl;
        return  ;
    }

    cout << -1 << endl;
    return ;
}

C. Beautiful XOR

位运算,就是比较二进制位,先判断a和b的二进制位长度,如果b比a长,那么无论怎样变化a都不能变成b。观察a与b的每位二进制位,只有两位互不相等时,加入1ll << i ,才能使a的那位二进制变成b的那位二进制

查看代码
void solve(){
    int a, b;
    cin >> a >> b;
    int idex= 0;
    while((1ll << idex) <= a) idex++;
    if(b >= (1ll<< idex)){
        cout << -1 << endl;
        return  ;
    }

    vector<int> arr;
    for(int i = 0; i < 32; ++i){
        int bita = (a >> i) & 1ll;
        int bitb = (b >> i) & 1ll;
        if((bita ^ bitb) == 1){
            arr.emplace_back(1ll << i);
        }
    } 

    if(arr.empty()){
        cout << 0 << endl;
        return ;
    }else{
        cout << arr.size() << endl;
        for(auto x : arr){
            cout << x << " ";
        }
        cout << endl;
    }
    return ;
}

D. Beautiful Permutation

二分法,第一次通过“1 1 n”得到原始数组的和pre,在通过“2 1 n”得到修改后的数组和sum,则被修改的区间长度就是len = sum - len,通过二分法,每次获取1到mid区间原始数组和修改后数组的和ppre和ssum,如果ppre == ssum 说明修改的区间在mid的右边,让left = mid + 1,如果不相等,则说明部分修改的区间是在1到mid之间的,则让ans = r; r = mid - 1.二分终止后得到的ans就是修改区间的左边,我们一致修改的区间长度为len,则修改区间的右边就为ans + len - 1.

查看代码
void solve(){
    int n;
    cin >> n;
    int pre = (1 + n) * n / 2;
    cout << "2 1 " << n << endl;
    int sum;
    cin >> sum;
    int len = sum - pre;
    int l = 1, r = n;
    int ans = n;
    while(l <= r){
        int mid = (l + r) >> 1;
        cout << "1 1 " << mid << endl;
        int ppre;
        cin >> ppre;
        cout << "2 1 " << mid << endl;
        int ssum;
        cin >> ssum;
        if(ppre == ssum){
            l = mid + 1;
        }else{
            ans = mid;
            r = mid - 1;
        }
    }
    cout << "! " << ans << " " << ans + len - 1 << endl;
    return ;
}

E. Beautiful Palindromes

这是一道结论题,如果想让加入k个数构成的新数组产生的子回文数最少,那么应该尽可能得让加入的k个数不会与原来的数组产生回文数,也不能让加入的k个数内部产生回文数。因此,我们可以选择3个不同的数“xyz”构成循环,“xyzxyzxyz...”这样排列能确保加入的数内部不会产生回文数,那么,应该如何选取这三个数呢?

根据题目我们能知道,数组元素的取值是在1到n之间的,如果加入一个1到n的数在原数组从来没有出现的数,那么加入的这个数就不会与原数组任何一个数产生回文。如果未出现的数不满足三个,剩下的数应从原数组从后往前记录不同的数直到补全,并且按照顺序排列,比如,对于一个n = 6 的,原数组是【1,2,3,4,4,5】,从未出现的数是6,那么我要补全2个数,从后往前取应该是5与4,如果不想产生回文,我的“xyz”排列应该是645,如果y与z调换,那么这个排列就会与原数组最后两位产生回文。

最后,遍历k次,每遍历3次从来再来,构成循环。

查看代码
void solve(){
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 1, 0);
    set<int> st;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        st.insert(a[i]);
    }

    vector<int> v;
    for(int i = 1; i <= n; ++i) if(st.count(i) == 0) v.emplace_back(i);
    if(st.size() == n){
        v = {a[n - 2], a[n - 1], a[n]};
    }else if(st.size() == n - 1){
        if(a[n] == a[n - 1]) {
            v.emplace_back(a[n - 2]);
            v.emplace_back(a[n]);
        }else{
            v.emplace_back(a[n - 1]);
            v.emplace_back(a[n]);
        }
    }else if(st.size() == n - 2){
        v.emplace_back(a[n]);
    }

    int cnt = 0;
    for(int i = 0; i < k; ++i){
        if(cnt == 3) cnt = 0;
        cout << v[cnt] << " ";
        cnt++;
    }
    cout << endl;
    return ;
}

 

posted @ 2025-10-20 16:33  菜鸡の编程日常  阅读(18)  评论(0)    收藏  举报