• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

yumiym765

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

E. Product of Closures

E. Product of Closures

​ 设 \(C(x)\) 表示 \(x\) 的无前导零二进制表示重复无限次拼接,例如:\(C(4) = 10010010010010...\)。

​ 给定 \(l, r, n\),求解 \(x\) 和 \(y\) (\(l \le x \lt y \le r\)),使得 \(C(x) \mathop{\&} C(y)\) 的二进制表示字典序最小,输出 \(C(x) \mathop{\&} C(y)\) 的前 \(n\) 二进制位。

​ 多测,\(1 \le t,n \le 1000\), \(1 \le l \lt r \lt 2^{30}\)。

​ 链接:CF2242E

​ 设 \(kr = \lfloor \log_{2}{r} \rfloor\),\(kl = \lfloor \log_{2}{l} \rfloor\),以下长度均为二进制表示的长度。分三类讨论。

​ 情况 1:\(kl = kr\)。最终的数是长度为 \(kr\) 的无限循环,我们尽量要使得二进制位不同,发现如果某一位 \(l_i \neq r_i\),那一定是 \(l_i = 0,r_i = 1\),我们就可以使 \(r_j(j > i)\) 为 \(0\),那么后面位置的答案就都是 \(0\) 了。

​ 情况 2:\(kl + 1 = kr\)。最终的数是长度为 \(k = kl \times kr\) 的无限循环,由于 \(kl < kr\),那么 \(y\) 除了首位都可以是 \(0\),即 \(x = l,y = 2^{kr}\)。拼接求解即可。

​ 情况 3:\(kl + 1 < kr\)。最终的数是长度为 \(k = \text{lcm}(kl,kr)\) 的无限循环,可以有 \(x = 2^{kr - 1},y = 2^{kr}\)。这样 \(k\) 最大,并且只有循环首位是 \(1\),拼接求解即可。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using i128 = __int128;
const double PI = acos(-1.0);
const int MOD = 1000000007; // 998244353
#define MAXN 100005

string trans(int x){
    string res;
    while(x > 0){
        if(x & 1)   res += "1";
        else    res += "0";
        x >>= 1;
    }
    reverse(res.begin(), res.end());
    return res;
}
int getLen(int x){
    int res = 0;
    while(x > 0){
        res++;
        x >>= 1;
    }
    return res;
}
void print(string s, int len){
    int cnt = 1;
    while(cnt <= len){
        for(int i = 0;cnt <= len && i < s.length();cnt++, i++){
            cout << s[i];
        }
    }
    cout << "\n";
}
void solve(){
    int l, r, n;
    cin >> l >> r >> n;
    int kr = getLen(r), kl = getLen(l);
    if(kl == kr){
        string L = trans(l), R = trans(r);
        bool flag = false;
        for(int i = 0;i < kl;i++){
            if(L[i] != R[i]){
                flag = true;
            }
            if(flag)    L[i] = '0';
        }
        print(L, n);
    }else if(kl + 1 == kr){
        string L = trans(l), R = trans(r);
        for(int i = 1;i < kr;i++)   R[i] = '0';
        string tL = L, tR = R;
        int K = kr * kl;
        for(int i = 1;i < kl;i++)   R += tR;
        for(int i = 1;i < kr;i++)   L += tL;
        for(int i = 0;i < K;i++){
            if(L[i] != R[i])    L[i] = '0';
        }
        print(L, n);
    }else{
        int K = kr * (kr - 1);
        string res = "1";
        for(int i = 1;i < K;i++){
            res += "0";
        }
        print(res, n);
    }
}

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

做这题的时候想到寒假营的类似的题还没补,于是去补了 pwp。

AND vs MEX

​ 给定 \(l, r\),初始有一个可重整数集合 \(\Bbb{S}\),可以进行任意次以下操作。

​ 从区间 \([l, r]\) 中选择至少一个不同的整数,将这些整数的 \(\text{AND}\) 加入集合 \(\Bbb{S}\) 中。

​ 请最大化 \(\Bbb{S}\) 的 \(\text{MEX}\)。

​ 多测,\(0 \leq l \leq r < 2^{30}\)。

​ 链接:https://ac.nowcoder.com/acm/contest/120561/I

​ 设 \(kr = \lfloor \log_{2}{r} \rfloor\),\(kl = \lfloor \log_{2}{l} \rfloor\),以下长度均为二进制表示的长度。分三类讨论。

​ 特判:\(l = 0\) 时可以取到 \([0, r]\) 所有数字,答案为 \(r + 1\)。

​ 情况 1:\(kl = kr\)。最高位相同,发现无法得到 \(0\),所以答案为 \(0\)。

​ 情况 2:\(kl + 1 = kr\)。取 \(L\) 为 \(2^{kl} - 1\),即全 \(1\),\(R\) 为 \([2^{kr-1},r-2^{kr-1}] = [2^{kl},r-2^{kl}]\),可以得到 \([0, r - 2^{kl}]\)。考虑 \((r - 2^{kl}, l)\) 的范围能否取到,设 \(l = 1101100\),可以取 \(x = 1101111,y = [1110000,1111111]\),做与运算,得到 \([1100000, L]\),这样就能得到 \(L\) 的下限位,然后交起来就可以了。

​ 情况 3:\(kl + 1 < kr\)。取 \(L\) 为 \([2^{kl + 1},2^{kl} - 1]\),\(R\) 为 \(2 ^ {kr}\)。这样可以得到 \([0, 2^{kl + 1} - 1]\),由于 \(2^{kl + 1} - 1 \ge l\),所以最终可以取得 \([0,r]\),答案为 \(r + 1\)。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using i128 = __int128;
const double PI = acos(-1.0);
const int MOD = 1000000007; // 998244353
#define MAXN 100005

int getLen(int x){
    int res = 0;
    while(x > 0){
        res++;
        x >>= 1;
    }
    return res;
}

void solve(){
    int l, r;
    cin >> l >> r;
    int kr = getLen(r), kl = getLen(l);
    if(l == 0){
        cout << r + 1 << "\n";
    }else if(kl == kr){
        cout << "0\n";
    }else if(kl + 1 == kr){
        int now1 = r - (1 << (kr - 1)) + 1;
        int now2 = 0;
        for(int i = kl - 1;i >= 0;i--){
            if(((l >> i) & 1)){
                now2 += (1 << i);
            }else{
                break;
            }
        }
        if(now2 <= now1)    cout << r + 1 << "\n";
        else    cout << now1 << "\n";
    }else{
        cout << r + 1 << "\n";
    }
}

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

posted on 2026-07-10 17:58  羊毛corn  阅读(9)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3