B. And It‘s Non-Zero

题目链接:https://codeforces.com/problemset/problem/1615/B

位运算之前没怎么写过,所以不会写。留一份题解,作为复习使用。

题解:按位与的结果不为0,则至少有一列全为1.要求删除的数最少,即要求该列原本含有的1最多。则统计每一位的1的个数,找出个数最大值,用数组数字的总数,减去1的个数,即需要删除的个数。

第一版写的是枚举每一个数,对每一个数的每一位用&(1<<j)判断是不是1,用一个数组来统计每一位的结果。然而是TLE...

第二版,借助AI工具,发现了从0开始到某一位的数据的二进制排列规律,用前缀和求解可得。

背景知识

在二进制表示中,每一位(bit)会以固定的周期出现 0 和 1。例如:

  • 第 0 位(最低位):0, 1, 0, 1, 0, 1, ...,周期为 2。
  • 第 1 位:0, 0, 1, 1, 0, 0, 1, 1, ...,周期为 4。
  • 第 2 位:0, 0, 0, 0, 1, 1, 1, 1, ...,周期为 8。

我们可以直接计算某一位为 1 的数量,而不需要逐个遍历每个数字。


公式解释

1. 完整周期的贡献

对于第 j 位:

  • (1 << (j + 1)) 个数字中,第 j 位会有连续 (1 << j) 个 1。
  • 例如:
    • 第 0 位:每 2 个数字中有 1 个 1。
    • 第 1 位:每 4 个数字中有 2 个 1。
    • 第 2 位:每 8 个数字中有 4 个 1。

完整的 (1 << (j + 1)) 块的数量为:(r + 1)/(1 << (j + 1)) +1是因为0也要算进去

这些完整块中,第 j 位的 1 的总数为:(r + 1)/(1 << (j + 1)) * (1 << j)

2. 剩余部分的贡献

可能还有一部分数字不足一个完整的 (1 << (j + 1)) 块,这部分的长度为 (r + 1) % (1 << (j + 1))

在这部分中,第 j 位为 1 的数量为:

  • 如果剩余部分长度大于 (1 << j),那么第 j 位会有 (r + 1) % (1 << (j + 1)) - (1 << j)个 1。
  • 如果剩余部分长度小于等于 (1 << j),那么第 j 位会有 0 个 1。
3. 总计第 j 位的 1 的数量

将完整周期和剩余部分的贡献相加

代码如下:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;


void count(int r,int*arr)
{
    for(int i=0;i<20;i++)
    {
        int num=0;

        int period=(1<<(i+1));
        int full_p=(r+1)/period;
        int remain=(r+1)%period;
        if(remain>(1<<i))
        {
            num=full_p*(1<<i)+remain-(1<<i);
        }
        else
        {
            num=full_p*(1<<i);
        }
        arr[i]=num;
    }
}



int main()
{
    int t;
    cin>>t;
    int ans[t];
    int k=0;
    while(t--)
    {
        int l,r;
        cin>>l>>r;
        
        int arr_l[20];
        int arr_r[20];
        count(l-1,arr_l);
        count(r,arr_r);
        
        int max=0;
        for(int i=0;i<20;i++)
        {
            if((arr_r[i]-arr_l[i])>max)
            {
                max=arr_r[i]-arr_l[i];
            }
        }
        ans[k++]=r-l+1-max;

    }
    for(int i=0;i<k;i++)
    {
        cout<<ans[i]<<"\n";
    }
    return 0;
}
相关推荐
码破苍穹ovo3 小时前
堆----1.数组中的第K个最大元素
java·数据结构·算法·排序算法
愤怒的小鸟~~~4 小时前
c语言创建的一个队列结构(含有这个头指针和这个尾指针的结构具有一定的参考价值)
c语言·开发语言·算法
Joker-01115 小时前
深入 Go 底层原理(十二):map 的实现与哈希冲突
算法·go·哈希算法·map
金融小师妹6 小时前
AI量化模型解析黄金3300关口博弈:市场聚焦“非农数据”的GRU-RNN混合架构推演
大数据·人工智能·算法
金融小师妹6 小时前
基于LSTM-GRU混合网络的动态解析:美联储维稳政策与黄金单日跌1.5%的非线性关联
大数据·人工智能·算法
白日梦想家-K7 小时前
题单【模拟与高精度】
开发语言·c++·算法
重生之我是Java开发战士7 小时前
【C语言】内存函数与数据在内存中的存储
c语言·开发语言·算法
roman_日积跬步-终至千里8 小时前
【机器学习】“回归“算法模型的三个评估指标:MAE(衡量预测准确性)、MSE(放大大误差)、R²(说明模型解释能力)
算法·机器学习·回归
小指纹9 小时前
图论-最短路Dijkstra算法
数据结构·c++·算法·深度优先·图论
赴33511 小时前
逻辑回归 银行贷款资格判断案列优化 交叉验证,调整阈值,下采样与过采样方法
算法·机器学习·逻辑回归·下采样·交叉验证·过采样·阈值