• MAX(数论)


    Description

    小C有n个区间,其中第i个区间为[li,ri],小C想从每个区间中各选出一个整数,使得所有选出的数and起来得到的结果最大,请你求出这个值。

    Input Format

    第一行一个正整数n,表示区间个数。接下来n行,每行两个非负整数li,ri。

    (n leq 10^5, li leq ri leq 10^{18})

    Output Format

    输出一个整数,表示答案。

    Solution

    跟二进制有关,那么一般都要转化成二进制下操作,

    我们发现,最后的答案其实是可以看成(2^{k_1}+2^{k_2}+...2^{k_n}),

    那么其实就是选出来的数列化成二进制后第(k_1,k_2...k_n)位都为1,

    (k_i)越大就越优,那么就有了思路,按二进制为从高到低验证,

    如果第(i) 位符合条件,那么(Ans+=2^i) ,答案就算出来了,

    当符合条件的时候,需要特殊处理否则会影响到后面的判断,

    只要把所有区间都往左移动(2^i)即可,即减去(2^i),

    Code

    #include <cstdio>
    #include <algorithm>
    #define LL long long
    #define N 100010
    using namespace std;
    
    int n;
    LL Ans, l[N], r[N];
    
    inline LL read() {
    	LL x = 0, r = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') {if (ch == '-')r = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    	return x * r;
    }
    
    int main() {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i)
    		l[i] = read(), r[i] = read();
    	for (int k = 62; k >= 0; k--) {
    		LL pk = 1ll * 1 << k;
    		bool flag = 1;
    		for (int i = 1; i <= n; ++i)
    			if (r[i] < pk) flag = 0;
    		if (flag) Ans += pk;
    		for (int i = 1; i <= n; ++i) {
    			if (flag || l[i] >= pk) l[i] -= pk, r[i] -= pk;
    		}
    	}
    	printf("%lld
    ", Ans);
    	return 0;
    }
    
  • 相关阅读:
    背包问题--动态规划
    day03_13 多分支if语句及作业
    day03_12 缩进介绍
    day03_11 if语句实现猜年龄01
    day03_10 注释及简单的用户输入输出
    day03_09 编码部分历史及文件编码简介
    day03_07 变量的重新赋值01
    day03_06 变量详解
    day03_05 Python程序文件执行和与其他编程语言对比
    day03_04 文件后缀及系统环境变量
  • 原文地址:https://www.cnblogs.com/void-f/p/7747351.html
Copyright © 2020-2023  润新知