Dual horsetail
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 500 Accepted Submission(s): 189
Problem Description
Nanaya‘s favorite Dual horsetail robot has run out of power!
As a best friend of Nanaya, Cdfpysw decide to do something for him.
Cdfpysw, the king of alpaca, has some very powerful energy balls numbered by 1,2,3……n. He let Nanaya divide them into some sets to save the robot.
However, if there are three balls whose numbers are labeled X,Y and X&Y in the same set, they will explode! Nanaya must divide these balls into some sets and avoid explosion.
Nanaya is a shy man, he don‘t want to divide these balls into too many sets. Please tell him the minimum number of sets.
Input
The first line contains an integer T, indicating the number of cases.
The next T line, each line contains an integer n indicating the number of balls. (1 <= n <= 109)
Output
For each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y represents the minimum number of sets.
Sample Input
2
2
3
Sample Output
Case #1: 1
Case #2: 2
算法与题目分析:T组数据,每组输入一个n,代表1到n的数据。现在要把这n个数放到一些集合里,求最少的集合数目。
必须满足条件:x, y和(x&y),这三个元素不会同时出现在一个集合了!
先需要知道一些特殊数字的二进制写法:
十进制----------二进制
1 0001
3 0011
7 0111
15 1111
31 0001 1111
......
规律是:我们从1开始处理数据,当出现一个新的数字,而这个数字的二进制表示全都是1(忽略前导0),就
必须把这个数字放到一个新增加的集合里面,否则这个数字会与前面的某些数字必定不会满足要求条件。
n的范围(1 <= n <= 109),所以只需要找出所有的二进制表示全为1的数字的个数。注意不需要把1到n的数据
挨着进行进制转换。我们只需要进行一个循环即可。二进制表示全为1的这些数是有规律的,如果你了解二进制转十进制
的算法就会懂的!
例如:1 = 2^0.
3 = 2^0+2^1.
7 = 2^2+2^1+2^0.
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <math.h> #include <iostream> #include <string> #include <algorithm> #define PI acos(-1.0) #define INF 1e9 using namespace std; int dd[100]; int main() { int t; scanf("%d", &t); int n; memset(dd, 0, sizeof(dd)); int ans; int e=1; dd[e++]=1; ans=1; int i=1; while(ans < INF ) { ans=ans+pow(2, i); i++; dd[e++]=ans; } // printf("-----%d\n", i); int cnt=1; while(t--) { scanf("%d", &n); int pos; for(i=0; i<e; i++) { if(n>=dd[i] && n<dd[i+1]) { pos=i; break; } } printf("Case #%d: %d\n", cnt++, pos ); } return 0; }