• CFdiv2-Common Number-(奇偶数二分+规律)


    E

    题意:
    就是给你一个函数f(x) = x/2(如果x是偶数),f(x) = x-1(如果x是奇数且不为1)。定义path(15) = [15,14,7,6,3,2,1]。也就是他会走的数字直到为1。然后给你一个k,问你哪个数字在>=k个不同的path中出现过,如果有多个,输出最大的那个数。

    思考:

    1. 既然问最大的,那么肯定可以二分,手推了推发现越小的数字出现在的path越多,那么就肯定是满足单调性的。然后比如check(mid),怎么算mid出现的path?
    2. 如果x是奇数,那么x包含在path(x),path(2x),path(2x+1),path(4x),path(4x+1),path(4x+2),path(4x+3)。发现最初的起点就是x第一层一个数,然后一直往下面拓展,每拓展一次就是一层的数。
      如果x是偶数,那么x包含在path(x),path(x+1),path(2x),path(2x+1),path(2x+2),path(2x+3)。发现最初的起点是[x,x+1]第一层两个数,然后拓展,每次拓展就是一层。
    3. 刚开始我这样想的时候,感觉你这递归多少次呀,肯定超时了,虽然看起来像log,但是如果暴力dfs去搜每个分支这就是O(n)的。但是如果我每次只存这一层的两个端点呢?那么是不是就log(n)了。为什么每次都是一层呢?画图会发现,这就是一层一层连续的数。
    4. 图片引自其他博客
    5. 然后我就去写了,但是发现不对呀。看了看图发现,并不是整个数都是单调的,而是分奇数偶数的。1>3>5>7…,2>4>6>8…,但是2并不大于3。所以两次二分,一次二分奇数一次二分偶数,每次取最大值就可以了,注意奇数偶数二分的写法。

    代码:

    #include
    #define fi first
    #define se second
    #define pb push_back
    #define db double
    #define int long long
    #define PII pair<int,int >
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    		
    using namespace std;
    const int mod = 1e9+7,inf = 1e18;
    const int N = 2e5+10,M = 2010;
    
    int T,n,m,k;
    
    int get(int x)
    {
    	queue<PII > q;
    	if(x&1) q.push({x,x}); //这一层的左右区间,奇数就自己
    	else q.push({x,x+1}); //偶数是两个
    	int sum = 0;
    	while(q.size())
    	{
    		auto now = q.front();q.pop();
    		sum += min(n,now.se)-now.fi+1; //这段区间可以加多少数
    		if(now.fi*2<=n) q.push({now.fi*2,now.se*2+1}); //如果还可以扩展
    	}
    	return sum;
    }
    
    bool check(int mid)
    {
    	int sum = get(mid);
    	return sum>=k;
    }
    
    signed main()
    {
    	IOS;
    	cin>>n>>k;
    	int maxn = 0;
    	int l = 1,r = n&1?n:n-1; //初始范围
    	while(l<=r) //l<=r
    	{
    		int mid = (l+r)>>1;
    		if(mid%2==0) mid--; //如果不是奇数-1
    		if(check(mid))
    		{
    			l = mid+2; //+2
    			maxn = max(maxn,mid); //答案要在这里面更新
    		}
    		else r = mid-2; //-2
    	}
    	l = 2,r = n&1?n-1:n;
    	while(l<=r)
    	{
    		int mid = (l+r)>>1;
    		if(mid%2!=0) mid--;
    		if(check(mid))
    		{
    			l = mid+2;
    			maxn = max(maxn,mid);
    		}
    		else r = mid-2;
    	}
    	cout<<maxn;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    总结:
    多多思考,画图模拟模拟。

  • 相关阅读:
    Power BI 自定义门户----大成
    zookeeper本地安装启动
    OpenGL官方文档中的入门教程源代码:在3维空间中自由移动
    抓到Dubbo异步调用的小BUG,再送你一个贡献开源代码的机会
    javaSE的整体回顾
    《计算机体系结构量化研究方法第六版》1.6 成本趋势
    电脑怎么格式化清除所有数据
    [springMVC学习]5、模型数据处理
    Code Llama: Open Foundation Models for Code
    微软放大招!Bing支持DALL-E3,免费AI绘画等你来体验!
  • 原文地址:https://blog.csdn.net/m0_52398496/article/details/126266812