专栏文章

题解:P13995 【MX-X19-T4】「FeOI Round 4.5」Supernova

P13995题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@minz3otc
此快照首次捕获于
2025/12/02 10:42
3 个月前
此快照最后确认于
2025/12/02 10:42
3 个月前
查看原文
不难发现第 22 次操作至多进行 11 次,因为在进行了 11 操作以后相同的操作可以用一次 11 操作替代。此时我们如果需要进行 22 操作,当且仅当第一次进行 22 操作更优且不会超过 yy。如果不进行 22 操作,我们进行一次 11 操作,使得 pp 成为 xx 的子集。
然后我们考虑 11 操作的本质:考虑其补集,进行一次 11 操作相当于枚举子集,因此我们只要算出来 xxyy 补集在 pp 补集的子集中的顺序然后相减再加 11 就可以了,而计算顺序也很简单,对二进制拆分后的每个 2n2^n 找一下子集中比自己小的数然后加起来就可以。时间复杂度 O(Tlogn)O(T\log n)。(还有就是,这题怎么评上蓝的?)
CPP
#include<bits/stdc++.h>
#define int long long
#define mp make_pair
#define fi first
#define se second
#define lb lower_bound
#define fr front()
#define pii pair<int,int>
#define INF (1ull<<63)-1
#define bp __builtin_popcountll
using namespace std;

int t,x,y,p,maxn=INF;

signed main(){
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--){
        cin>>x>>y>>p;
        if(x==y){
            cout<<0<<"\n";continue;
        }
        if((x|(p+1))==y||((x+1)|p)==y){
            cout<<1<<"\n";continue;
        }
        int num=1,nxt=(x|(p+1));
        if(nxt>((x+1)|p)&&(nxt&p)==p&&nxt<=y)x=nxt;
        else x=(x+1)|p;
        if(x==y){
            cout<<1<<"\n";continue;
        }
        if(y<x||(y&p)!=p){
            cout<<-1<<"\n";continue;
        }
        int nx=(maxn^x),ny=(maxn^y);p=(maxn^p);
        int ax=0,ay=0;
        for(int i=0;i<=62;i++){
            if(nx&(1ll<<i)){
                int k=((1ull<<i)-1)&p;
                ax+=(1ull<<bp(k));
                //cout<<k<<" "<<bp(k)<<" "<<ax<<"\n";
            }
        }
        for(int i=0;i<=62;i++){
            if(ny&(1ll<<i)){
                int k=((1ull<<i)-1)&p;
                ay+=(1ull<<bp(k));
                //cout<<k<<" "<<ay<<"\n";
            }
        }
        //cout<<ax<<" "<<ay<<" ";
        cout<<ax-ay+1ll<<"\n";
    }
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...