B. Turtle and an Infinite Sequence区间或和

题目链接

        区间或和有公式,如果求的是【l,r】区间或和,设x是l和r从高位到低位第一位二进制不同的位置,那么ans就是  l   | ((1<<(x+1))-1)  ,比如101111 和100111答案就是100111 | 1111

        也可以去n值去判断它的每一位是否可以取到1,如果n值本身有1,ans该位就有1。我们设判断的位置是d位,那么我们看看它能不能从小的数(左边的数)或过来,比如n=10011,l=100,那么第3一位0其实可以或上100。我们令x为n%2^d, x就是11,如果n大于等于2^d(前提条件),且n可以减去x+1(也就是说让n变成1111,也就是从前面借位,让后面都是1,可以减去x+1表示左区间长度大于等于x+1),表示该为1可以从左区间获得,或者说该位的0就是左区间为1时进位得到的。

        也可以去判断右区间。n离进位最近距离就是2^d-x,如果右区间包括了这个长度,也可以得到1.

        最后只需要判断min(x+1,2^d-x)是否<=m即可(前者得保证n大于等于2^d,也就是说存在高位).

代码1:

        

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
const int inf=0x3f3f3f3f;
const int N=1e6+10;
const int mod=1e9+7;
const ll INF=2e9+10;
mt19937_64 rd(23333);
uniform_real_distribution<double> drd(0.000001,0.99999);



void solve(){
    int n,m,l,r;
    cin>>n>>m;
    l=max(0ll,n-m),r=n+m;
   	int ans=l;
	for(int i=40;i>=0;i--){
		if((1ll<<i)&(l^r)){
			ans|=((1ll<<(i+1))-1);
			break;
		}
	}
	
	cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

代码2:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
const int inf=0x3f3f3f3f;
const int N=1e6+10;
const int mod=1e9+7;
const ll INF=2e9+10;
mt19937_64 rd(23333);
uniform_real_distribution<double> drd(0.000001,0.99999);


int n;
int a[N];

void solve(){
    int n,m,l,r;
    cin>>n>>m;
    int ans=0;
	for(int i=0;i<=40;i++){
		if((n>>i)&1){
			ans|=(1ll<<i);
			continue;
		} 
		int x=n&((1ll<<i)-1);
		int t=(1ll<<i)-x;
		if(n>=(1ll<<i))
			t=min(t,x+1);
		//if(x>=(1ll<<i)||t<=m)
		if(t<=m)
			ans|=(1ll<<i);
	}
	
	cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值