今天参加周测,发现了一道精彩的题目;
题目如下
简单位运算
Problem Description
给你一个正整数n ,求出最大的k ,满足:n&(n−1)&(n−2)&⋯&k=0
Input
第一行包含一个整数t ,代表含有t 组测试样例
第二行到第t+1 行,每行仅包含一个整数n ,代表每一组测试样例中的n
保证:1≤t≤1e4 ,1≤n≤1e9
Output
输出t 行,对于每一组样例,输出最大的k (行末换行)
Sample Input
3 2 5 17
Sample Output
1 3 15
暴力解法较为容易在这里不做介绍,而且暴力解法是不能按时解决该问题的。
首先我们观察一下位运算如何得到0;必需所有位都与0按位与才行。
那这时我们不由的想到,随着一位一位的减小,每位会逐渐与0相与,直到最高位也为0。于是乎问题就找到突破口了,就是找到最有效高位为0的最大数。
eg;001000110111011
只需;000111111111111
即可也就是2^n-1的值。
下面是AC的代码:
#include<stdio.h>
//#include<math.h>
//int main()
//{
// int i, n, t, j, a[10000];
// float k;
// scanf("%d", &t);
// for (i = 0; i < t; i++)
// {
// scanf("%d", &n);
// k = n;
// for (j = 1; j < n; j++)
// {
// k = k / 2;
// if (k < 2)
// {
// a[i] = pow(2, j) - 1;
// break;
// }
// }
// }for (i = 0; i < t; i++)
// printf("%d\n", a[i]);
// return 0;
//}
这里我求指数还是复杂了,可以直接用位运算符解决(新手上路还请多多包涵。)