Neko Performs Cat Furrier Transform CodeForces - 1152B 二进制思维题

Neko Performs Cat Furrier TransformCodeForces - 1152B   

  题目大意:给你一个x,在40步操作以内把x变成2m1,m为非负整数。对于每步操作,奇数步可以在(0<=n<=30)中挑选一个n,将x(2n1),而偶数步将x++。输出操作步数,以及在每个奇数步异或的n,多个答案,输出任一答案,保证至少有一个答案。

  一开始傻逼了,真的照题意所说的去写了一个深搜,果断超时了。其实每个奇数步也是异或一个二进制全1的数,那我们就直接把x尾部连续0部分,全部异或为1,那么在偶数步加1的话,又会往前进位填补前面的0(如果有的话0),然后再继续把x尾部连续0部分,全部异或为1,直到x为二进制全1即可。

  就比如x=80,二进制为1010000,我们第一步先异或个24-1=15即1111,x就变成了95=1011111,然后第二步x++,x就成了96=1100000,第三步在异或个25-1=31即11111,x变成了127=1111111,结束。

  因为1e6,最多就220左右,肯定不会超出40步。而取得末尾连续0部分正是树状数组里的那个x&(-x),不懂的可以去了解下。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cmath>
 4 #include<map>
 5 using namespace std;
 6 map<int,int> m;
 7 vector<int> ans;
 8 int main()
 9 {
10     int cf2=1;
11     //把终止情况,2^i-1标记一下
12     m[0]=1; 
13     for(int i=1;i<=30;i++)
14     {
15         cf2<<=1;
16         m[cf2-1]=1;
17     }
18     int x,step=0;
19     scanf("%d",&x);
20     while(!m[x])
21     {
22         step++;
23         if(step&1)
24         {
25             int y=x&(-x),n=0;
26             x^=(y-1);
27             while(y)
28             {
29                 n++;
30                 y>>=1; 
31             }
32             //y=2^(n-1) 
33             ans.push_back(n-1);  
34         }
35         else
36             x++;
37     }
38     printf("%d\n",step);
39     for(int i=0;i<ans.size();i++)
40     {
41         if(i)
42             putchar(' ');
43         printf("%d",ans[i]);
44     } 
45     printf("\n");
46     return 0;
47 }
慢慢来不急

 

posted @ 2019-04-25 14:43  新之守护者  阅读(422)  评论(0编辑  收藏  举报