题目来源:http://116.56.140.75:8000/JudgeOnline/problem.php?id=1743
1743: 不唯一的计数法
时间限制: 1 Sec 内存限制: 64 MB题目描述
科学家在考古时发现一个远古部落的计数法非常奇怪。在通常的二进制计数法中每位上的数字只能是0或1,并且对于给定数的计数表示是唯一的。而这种计数法中的位权与二进制计数法相同,但是每个位可以取0、1、2三个数字。显然,使用这种计数法表示某个数时,其计数表示不一定唯一。例如:十进制的10可以表示成:1010,210,1002,202,122,共有5种表示法,8可以表示成1000,200,120,112共4种。现在,科学家感兴趣的是对于一个给定的十进制数n,想知道用这样的计数法表示共有多少种不同的表示法。
输入
第一行,一个整数k(1≤k≤100),表示测试用例的个数。其下的k行,每行包含一个整数n(1≤k≤2^31-1)。
输出
请参照输出用例的格式,输出f(n),每个输出单独占一行。
样例输入
6
1
7
10
1024
2147483647
2147483646
样例输出
f(1)=1
f(7)=1
f(10)=5
f(1024)=11
f(2147483647)=1
f(2147483646)=31
解析:我们应该清楚地认识到,10可以替换为02,20可以替换为12,100,类似这样,进行第一次变换,然后同样处理,直至不再能够变换为止。当然,暴力解决也是可以的,但注意强加剪枝条件,否则时间复杂度就可能很高了
代码:
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int a[40];
int t;
cin >> t;
int num;
int count;
while (t--)
{
memset(a, 0, 40);
long long int n, N;
cin >> n;
N = n;
num = 0;
while (n != 0)
{
a[num++] = n % 2;
n >>= 1;
}
count = 1;
int flag = 1;
int ok = 0;
while (flag == 1)
{
flag = 0;
for (int i = num - 1; i >= 1; i--)
{
if (a[i] == 1 && a[i - 1] == 0)
{
if (i == num - 1)
{
a[i - 1] = 2;
count++;
num--;
}
else
{
a[i] = 0;
a[i - 1] = 2;
count++;
}
flag = 1;
}
else if (a[i] == 2 && a[i - 1] == 0)
{
a[i] = 1;
a[i - 1] = 2;
if (!ok)
count++;
else
count += 2;
flag = 1;
}
}
ok = 1;
}
cout << "f(" << N << ")=" << count << endl;
}
}
/**************************************************************
Problem: 1743
User: 201730685257
Language: C++
Result: 正确
Time:0 ms
Memory:1484 kb
****************************************************************/