首页 > 其他分享 >关于此题CF2061E_Kevin and And的一些总结

关于此题CF2061E_Kevin and And的一些总结

时间:2025-01-21 23:32:30浏览次数:1  
标签:__ ... CF2061E long builtin 此题 ans 操作 Kevin

传送门
题目大意:给定\(n\)个数\(a[1...n]\)和\(m\)个数\(b[1...m]\),并且给定整数k,求让任意\(i,j\)使\(a[i]&b[j]\)来替代\(a[i]\)后这\(n\)个数总和最小。

  • 首先我们看到题目给的m范围非常小,最大只有10,然后又问我们k次操作之后总和的最小值,第一反应是不是可以直接先求出每个\(a[i]\)分别执行\(1...k\)次操作后的最小,然后再用DP来做。然而我们发现,让一个数与上另一个数,得到的结果一定是小于等于当前这个数的(&的运算规则),那也就是说一个数每次和另一个数&操作得到的结果和它本身相比都伴随着减少或者不变,于是乎发现分本用不着DP,只需要直接贪心地每次操作都找减少的最多的那一个就可以了。时间复杂度\(O(n * 2^{m})\)
  • 这里我们先用状压预处理出\(b\)数组中任几个&操作的结果。再往后枚举每个\(a[i]\),对于当前\(a[i]\),我们都求出其最小的&上\(1...m\)个\(b\)中的数的结果装到一个数组中,最后排序取最大的前\(k\)个即可
#include<bits/stdc++.h>
    
using namespace std;

long long t;
const long long N = 2e5 + 10;
long long n,m,k,ans;
long long a[N],b[N];
    
void solve() {
    ans = 0;
    cin >> n >> m >> k;
    for(long long i = 1;i <= n;i++) cin >> a[i],ans += a[i];
    for(long long i = 0;i < m;i++) cin >> b[i];
    vector<long long> f(1100);
    f[0] = (1ll << 30) - 1;
    for(long long i = 1;i < (1 << m);i++) {
        long long u = __builtin_ctz(i);
        f[i] = f[i ^ (1 << u)] & b[u];
    }
    vector<long long> h;
    for(long long i = 1;i <= n;i++) {
        vector<long long> g(m + 1);
        for(long long j = 0;j < (1 << m);j++) {
            long long c = __builtin_popcount(j);
            g[c] = max(g[c],a[i] - (a[i] & f[j]));
        }
        for(long long j = 1;j <= m;j++)
            h.emplace_back(g[j] - g[j - 1]);
    }
    
    sort(h.begin(),h.end(),greater<int>());
    for(long long i = 0;i < k;i++) ans -= h[i];
    cout << ans << '\n';
}
    
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin >> t;
    while(t--) solve();
    
    return 0;
}
  • 这里又两个函数__builtin_ctz()__builtin_popcount(),分别求的是最后一个1后有多少个0和整个数有多少个1,类似的还有__builtin_clz()等函数,不仅方便而且性能也很优秀

标签:__,...,CF2061E,long,builtin,此题,ans,操作,Kevin
From: https://www.cnblogs.com/lwiwi/p/18684764

相关文章

  • [每日 B] Kevin and Geometry
    前言想着能做的题也不多,直接当每日一练的形式写就好了心态放平,冷静利用时间思路转化题意考虑一个等腰梯形的性质朴素的想法是,枚举\(b\),枚举\(c<b\),然后计算是否有对应的\(a\)满足\(\existsa,\existsa+2c\),特判\(c=0\)这样直接爆炸,考虑优......
  • [CF2048F] Kevin and Math Class 题解
    注意到这里有个区间的\(b_i\)最小。我们考虑每个\(b_i\)作为最小的时候各操作几次。显然每个\(b_i\)的【操作区间】更长是不劣的。于是这些个\(b_i\)是可以打成笛卡尔树,进行DP。想到这一点,DP便是不难的了。定义\(f_{i,j}\)为以\(i\)为根的子树内,最优操作后最大值......
  • 关于此题[ABC350E] Toward 0和[ABC188F] +1-1x2记忆化搜索的一些总结
    传送门1传送门2这两道题都有个特性,那就是数据范围到了\(10^{18}\),这会让我们想用记忆化搜索或者期望DP的想法望而却退但是实际上我们可以用map。有人会说,用map那时间上貌似也过不去啊!但是我们发现这两道题当中,我们可以进行的操作都有除法操作,这就有点像势能线段树,时间复杂度实......
  • 关于此题[ABC 387]C - Snake Numbers 数位DP的一些总结
    传送门这道题要求我们求[l,r]范围内所有的“蛇数”,即这个数的第一位严格大于它的其他位的数。看到数据范围并且发现答案区间可加减性联想到数位DP。其实有点类似模板题,与经典的数位DP题类似的,我们需要判断前导0,需要判断当前枚举的数是否是贴着所给的数,在此题中如果想要记忆化的......
  • 关于此题[ABC367E] Permute K times倍增思想的一些总结
    传送门第一次接触到倍增思想是用来求lca时,为了避免一层一层往上爬浪费时间复杂度。再后来就是区间DP中一小类问题或者是部分图上问题可以用倍增来优化。那么这道题其实可以看作图上问题来使用倍增优化。看到这道题的数据范围,K达到了\(10^{18}\)量级,这让我们不得不思考log级别往......
  • 关于此题[ABC367F] Rearrange Query随机化哈希的一些总结
    传送门这道题要求我们对于非常多的询问回答[l,r]、[L,R]这样两个区间内A、B数组中各个数的出现次数是否相同。看到这道题似乎想到了刚开始学编程的时候就想过的一个问题(bushi,那就是我能不能直接用,例如说这段区间和是否相同,或者说这段区间乘积之类的是否相同来判断这个区间各个数......
  • CF2048G Kevin and Matrices
    题意对满足以下条件的大小为\(n\timesm\)值域为\([1,k]\)的矩阵计数:\(\min_{1\lei\len}(\max_{1\lej\lem}a_{i,j})\le\max_{1\lej\lem}(\min_{i=1}^na_{i,j})\)模数\(998244353\)。\(nk\le10^6,m\le10^9\)分析不妨记\(r_i=\max_{1\lej\lem}a_{i,j},......
  • 关于此题CF[Hello 2025] 2057C - Trip to the Olympiad的一些总结
    传送门题目大意:给定两个数l,r,试求l~r中选三个数a,b,c,使得\((axorb)+(bxorc)+(axorc)\)的值最大。有关此类异或最大的题目,首先想到的是确定最高位,因为假如说异或后二进制下k位置为1,那么此时答案就已经比k位置不为1,而k以后的位置都是1的情况要大了。而观察l,r这两个数,我......
  • 关于此题[ABC382E] Expansion Packs 概率DP的一些总结
    传送门首先看到这道题,我们发现想要求收集K个卡牌的期望开包数,必须要先求出每个包开出0~n张卡各自的概率,于是预示着这道题将要进行两次概率DP。首先我们求每个包开出0~n张卡各自的概率。这个很好求,我们假设f[i][j]表示前\(i\)张卡中开出\(j\)张卡的概率,那么显然有:\(f[i][j]=p[......
  • 关于此题E - Maximize XOR(Atcoder ABC 386)搜索技巧的一些总结
    传送门题目要求n个数中选k个数异或起来最大,我们想到字典树中最大异或和这一经典问题,但是很明显字典树只能解决任选两个数的最大异或,而此题是任选k个,那我们走投无路只能考虑爆搜。首先可以很容易写出一个暴力的搜索:voiddfs1(longlongpos,longlongsum,longlongkk){i......