Codeforces Round #554 (Div. 2) B - Neko Performs Cat Furrier Transform

题目链接:https://codeforces.com/contest/1152/problem/B

题意:给你一个数x,你可以对其进行两种操作:

操作A: 选择一个非负数:n,然后将 x与(2^n - 1)进行异或

操作B: 将x自增1

其中第一种操作必选为A,然后紧跟着B操作,即操作必须为ABAB....A或ABAB..AB。要求最后的x可以变为

即x = (2^m - 1)

思路:用(2^m - 1)【全1的数】进行异或操作的结果为:取反。对于每次被B操作完的x,从右向左找出第一个0,然后算出从这位起一直到最后的位数cnt,用cnt个1的数进行异或一下,即把首位的0变为了1。这样不断下去,一定为将x变为全1。

技巧操作:位运算:

取出整数n在二进制表示下的第k位   ---》   (n >> k) & 1

取出整数n在二进制表示下的第0~(k-1)位   ---》   n & ((1 << k) -1 )

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define Fin             freopen("in.txt","r",stdin)
#define Fout            freopen("out.txt","w",stdout)
#define Case(T)         int T;for(scanf("%d",&T);T--;)
#define fo(i,a,b)              for(int i = a; i < b; ++i)
#define fd(i,a,b)              for(int i = a; i >= b; --i)
#define me(a,b) memset(a,b,sizeof(a))
#define fi(a,n,val)    fill(a,a+n,val)
#define Scand(n)       scanf("%d",&n)
#define Scand2(a,b)     scanf("%d%d",&a,&b)
#define Scand3(a,b,c)     scanf("%d%d%d",&a,&b,&c)
#define Scand4(a,b,c,d)     scanf("%d%d%d%d",&a,&b,&c,&d)
#define Scans(s)       scanf("%s",s)
#define random(a,b)    a+rand()%(b-a+1)
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b ? gcd(b,a%b): a; }
const int maxn = 1e4 + 50;
const int INFint = 0xffffff;
const ll INFll = (ll)1e18;

#ifndef ONLINE_JUDGE

#endif // ONLINE_JUDGE

inline int readint(){
    int sgn = 1; int sum = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if(ch == '-')   sgn = -sgn;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
        sum = sum*10+(ch-'0');
        ch = getchar();
    }
    return sgn*sum;
}

inline ll readll(){
    ll sgn = 1; ll sum = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if(ch == '-')   sgn = -sgn;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
        sum = sum*10+(ch-'0');
        ch = getchar();
    }
    return sgn*sum;
}

int n;

int calc(int n){
    int tmp = n;
    int num = 0;
    while(n >> 1){
        num++;
        n >>= 1;
    }
    num++;
    return num;
}

int fun(int n){
    int num = calc(n);
    // printf("num:%d\n", num);
    for(int i = num; i >= 1; --i){
        int tmp = (n >> (i-1)) & 1;
        // printf("i:%d tmp:%d\n", i, tmp);
        if(tmp == 0){
            return i;
        }
    }
    return 0;
}

int judge(int n){
    int num = calc(n);
    if(n == int(pow(2, num) - 1))
        return 1;
    return 0;
}

int main()
{
    #ifndef ONLINE_JUDGE
        //Fin;
    #endif // ONLINE_JUDGE
    // int t = 10;
    // while(t--){
    //     int n = readint();
    //     cout << fun(n) << endl;
    // }
    n = readint();
    if(fun(n) == 0){
        cout << 0;
        return 0;
    }
    int cnt = 0;
    vector<int> v;
    while(!judge(n)){
        // printf("before  n:%d\n", n);
        int num = fun(n);
        int tmp = pow(2, num) - 1;
        n ^= tmp;
        cnt++;
        // printf("num:%d tmp:%d n:%d cnt:%d\n", num, tmp, n, cnt);
        v.push_back(num);
        if(judge(n)){
            cout << cnt << endl;
            int Size = v.size();
            for(int i = 0; i < Size; ++i){
                if(i == 0)
                    cout << v[i];
                else
                    cout << ' ' << v[i];
            }
            break;
        }
        n++;
        cnt++;
        if(judge(n)){
            cout << cnt << endl;
            int Size = v.size();
            for(int i = 0; i < Size; ++i){
                if(i == 0)
                    cout << v[i];
                else
                    cout << ' ' << v[i];
            }
            break;
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章