Problem - 2146D1 - Codeforces &&Problem - D2 - Codeforces

Problem - 2146D1 - Codeforces

题意很简单 给定一个从0开始的排列 b 重排b 得到a 使得sum(a|b)最大 b按顺序给出

首先 a|b 操作 我们可以看作a+b-a&b 那么我们只需要让所有的a&b 的和最小即可 观察样例发现 所有的答案都是(n+1)*n 所以我们猜测 存在一种重新排列的方式 使得所有的a&b =0

首先对于r=2^k-1 的情况 也就是 r的所有位置为1 的时候 我们可以直接对称进行构造

比如r=15 我们可以0于15 1与14 2与13 也就是(r-i)&i 一定为0 因为r全为1 r-i 就是去掉了i中为1 的部分 与i进行& 操作结果一定是 0 所以对于这种情况我们可以直接倒序输出

当r不等于2^k-1的时候 也就是会多一位最高位的时候 我们发现 最高位有1 的部分 如果去掉最高位 那么他们剩下的部分和低一位的时候没有区别

换句话说

01 2 3 4 5 6 7 他们本来是对称对称进行&的 全部为0 但是如果当前多了一个8 和9

8和9 去掉最高位后就是 0 和1 而0和1 本来就是和7 和6 进行&操作 所以我们可以令8 9 看作0 1 与7 6 进行&操作 然后剩下的部分重复这一过程即可

形式的 我们找到最高与r一致 并且所有位为1 的值m m-i 与i一定是&后为0 的 我们令i在(m-r 到r)范围 这样剩下的部分重复进行操作即可

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+5;
int a[N];
void solve(){
    int l,r;
    cin>>l>>r;
    int n=r-l+1;
    int r1=r;
    cout<<(r+1)*r<<'\n';
    while(r1>=0){
        int bit=0;
        int tmp=r1;
        while(tmp){
            tmp/=2;
            bit++;
        }
        int m=(1<<bit)-1;
        int st=m-r1;
        for(int i=st;i<=r1;i++){
            a[i]=m-i;
        }
        r1=st-1;
    }
    for(int i=0;i<n;i++){
        cout<<a[i]<<' ';
    }cout<<'\n';

}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)solve();    
    return 0;
}

Problem - D2 - Codeforces

D2不同的地方在于 起点不是l 但是我们依旧可以用类似的想法 如果存在一个位分界线 那么就按照分界线两侧一一匹配 然后剩下一部分没有分界线 最高位相同 这些相同的最高位是一定要舍弃的 因为数目多 所以我们可以直接 不看高位 看下一位 然后重复这个子问题进行求解

代码实现如下:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+5;
int L;
int g(int x,int j){
    return (x>>j)&1;
}
int get(int x){
    int num=0;
    while(x){
        x/=2;
        num++;
    }
    return num;
}
void dfs(int l,int r,vector<int>&ans,int j){
    if(l>r)return ;
    if(l==r){
        ans[l-L]=l;return ;
    }
    int mid=l;
    while(mid+1<=r&&g(mid+1,j)==g(l,j)){
        mid++;
    }
    if(mid==r){
        dfs(l,r,ans,j-1);
        return ;
    }
    int tl=mid+1,tr=mid;
    while(tl-1>=l&&tr+1<=r){
        tl--;tr++;
        ans[tl-L]=tr;
        ans[tr-L]=tl;
    }
    dfs(l,tl-1,ans,j-1);
    dfs(tr+1,r,ans,j-1);
}
void solve(){
    int l,r,res=0;;
    cin>>l>>r;
    L=l-1;
    vector<int>ans(r-l+2,0);
    dfs(l,r,ans,get(r)-1);
    for(int i=l;i<=r;i++){
        res+=(ans[i-L]|i);
    }
    cout<<res<<'\n';
    for(int i=l;i<=r;i++){
        cout<<ans[i-L]<<' ';
    }
    cout<<'\n';

}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)solve();    
    return 0;
}
相关推荐
geneculture5 分钟前
本真信息观:基于序位守恒的融智学理论框架——人类认知第二次大飞跃的基础
人工智能·算法·机器学习·数据挖掘·融智学的重要应用·哲学与科学统一性·融智时代(杂志)
kronos.荒6 分钟前
动态规划——最长递增子序列系列问题(python)
算法·动态规划·最长递增子序列系列问题
生信研究猿23 分钟前
#P4625.第2题-大模型训练显存优化算法
算法
逻辑驱动的ken26 分钟前
Java高频面试考点14
开发语言·数据库·算法·哈希算法
故事还在继续吗30 分钟前
C++17关键特性
开发语言·c++·算法
Rabitebla33 分钟前
【数据结构】消失的数字+ 轮转数组:踩坑详解
c语言·数据结构·c++·算法·leetcode
菜菜的顾清寒35 分钟前
力扣100(20)旋转图像
算法·leetcode·职场和发展
Navigator_Z35 分钟前
LeetCode //C - 1025. Divisor Game
c语言·算法·leetcode
深念Y35 分钟前
王者荣耀与英雄联盟数值设计对比:穿透、乘算与加算、增伤乘算更厉害,减伤加算更厉害
数学·算法·游戏·建模·游戏策划·moba·数值
budingxiaomoli43 分钟前
优选算法-多源bfs解决拓扑排序问题
算法·宽度优先