寒假 周报

这周主要是打蓝桥杯的训练赛,一场牛客一场cf,cf现在处于部分第四题赛后能出的阶段。

蓝桥杯1的题补的差不多了,感觉蓝桥杯的题都是能补的,争取在开学前补完。

题目链接:https://codeforces.com/contest/2064/problem/D

题意:给定一个数组 a , n个元素,q次询问,给一个x,x能和比他小的数 异或,x = x^a[i],

i 从 1-n,最多可以 异或 几次;

正解是状压dp,数据结构,想了一个3log的写法。

发现和比他小的数 y 异或,如果 y 的最高位和 x 一样,异或后一定会降位。如果最高位比 x 小,对答案没影响。不断二分找最高位和 x 一样的 y 就可以了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int a[200010];
int c[200010];
vector<int>v[10010];
void solve(){
    int n,q;
    cin >> n >> q;
    for(int i = 1;i <= 30; ++i)v[i].clear();
    for(int i = n;i >= 1; --i) cin >> a[i];
    for(int i = 1;i <= n; ++i) c[i] = a[i]^c[i-1];
    for(int i = 1;i <= n; ++i) {
        int y = 0;
        int x = a[i];
        while( x ) {
            y++;
            x /= 2;
        }
        v[y].push_back(i);
    }
    while( q-- ) {
        int x;
        cin >> x;
        int ans = 0;
        for(int i = 1;i <= 30; ++i) {
            int y = 0;
            int xx = x^c[ans];
            while( xx ) {
                xx /= 2;
                y++;
            }
            int d = n+1;
            for(int j = 30;j > y; --j) {
                auto tt = upper_bound(v[j].begin(),v[j].end(),ans);
                if( tt != v[j].end() ) {
                    d = min(d,*tt);
                }
            }
            auto t = upper_bound(v[y].begin(),v[y].end(),ans);
            if( t == v[y].end() ) {
                ans = d-1;
                break;
            }
            if( *t >= d ) {
                ans = d-1;
                break;
            }
            d = *t;
            ans = d-1;
            if( (x^c[d-1]) >= a[d] ) ans = d;
            else break;
        }
        cout << ans << " ";
    }
    cout << endl;
}

signed main()
{
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while( T-- ) solve();
    return 0;
}

 还有一题有意思的

P10426 [蓝桥杯 2024 省 B] 宝石组合

一个lcm公式,化简为变成求 gcd(a[i],a[j],a[k]) 最小,原来lcm,gcd可以互相转换,都忘记了,让后用暴力枚举加枚举小技巧就可以写出来了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int a[200010];
void solve(){
    int n;
    cin >> n;
    for(int i = 1;i <= n; ++i) {
        int x;
        cin >> x;
        a[x]++;
    }
    int ansx = 0,ansy = 0,ansz = 0;
    for(int i = 1;i <= 100000; ++i) {
        int bj = 3;
        int x = 0,y = 0,z = 0;
        for(int j = i;j <= 100000; j += i) {
            while( a[j] && bj ) {
                if( bj == 3 )x = j,a[j]--,bj--;
                else if( bj == 2 )y = j,a[j]--,bj--;
                else z = j,a[j]--,bj--;
            }
        }
        if( !bj ) {
            ansx = x;
            ansy = y;
            ansz = z;
            
        }
        a[x]++;
        a[y]++;
        a[z]++;
    }
    cout << ansx << " " << ansy << " " << ansz;
}

signed main()
{
    //ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int T = 1;
    //cin >> T;
    while( T-- ) solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值