题目描述:
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
注意:需要提交的是一个整数,不要填写多余内容。
/*
0 1 4 9 16 25 36 49 64 81 100(重复) 121(重复)
首先要记录每一个无重复数的平方数的二进制
因为只平移个位数上的值
如0用0000000001表示 1用0000000010表示 4用00000010000表示 9用1000000000 16用0001000010
number[0] = 1
number[1] = 2
number[2] = 16//10000即4
number[3] = 512//10000000000 即9
*/
#include <iostream>
using namespace std;
#define MAX 100000
int repeat(long long square)
{
int recording = 0; //记录二进制转十进制的数值
do
{
int bit = square % 10;
if(((1 << bit) & recording) != 0)//判断是否有重复个数 ,不等于0则证明数值出现过
{
return 0;
}
recording = recording | (1 << bit);//将个位数上的二进制记录到0000000000里面
}while((square /= 10) != 0);
return recording;
}
void q_number(int number[], int &num)
{
num = 0;
for(int i = 0; i < MAX; i++)
{
if(repeat((long long)i*i))//传数值的平方的同时判断数值是否有重复数,平方数可能超过int类型最大值,所以要转换成long long 类型
{
number[num++] = repeat((long long)i*i);
//记录每个个位数平移之个位数数值之后的数转十进制的数值(方便判断是否有重复数值)
}
}
return;
}
int q_count(int n, int number[],int index)//n表示已有数值
{
int count = 0;//记录组合的个数
while(number[index] != -1)
{
if((n & number[index]) == 0)//判断新的数值与数组里面的数值是否相等
{
if((n | number[index]) == 1023)
//判断二进制时是否等于1111111111,即判断十进制数是否等于1023
{
count++;
}
else
{
count += q_count((n | number[index]), number, index+1);
//通过递归的方法来遍历数组进行组合
}
}
index++;
}
return count;
}
int main()
{
int number[MAX];//因为是10位数里面的平方所以可以用int存储
int num = 0;//记录number的下标
q_number(number,num);//求平方数的二进制(用十进制来存)
number[num] = -1;//用来记录末尾值,以便最后遍历时不用传递num个数的参数
//cout << "num = " << num <<endl;
cout << q_count(0,number,0) << endl;//求组合的个数
return 0;
}
最后的答案是300,及使用完0~9且无重复数的平方数组成的组合有300个。
总结:可以通过位移个位数来判断是否有重复的数值出现,并且可以通过将一个数值的个位数移动
如16 先将 (1 << 6) & 0000000000得到 0001000000
再将(1 << 1) & 0001000000 得到0001000010
最后将0001000010 转换为十进制得到66,即number[4] = 66;