题目描述
题目出处:https://www.lanqiao.cn/problems/653/learning/
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
把 0 ~ 9 这 10 个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:
0, 36, 5948721
copy
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
…
注意,0 可以作为独立的数字,但不能作为多位数字的开始。 分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
运行限制
最大运行时间:1s
最大运行内存: 128M
思路:
利用二进制数的特点,记录每一个平方数的各个位的数的使用情况,再枚举算出满足题意的平方数并存储其状态。然后dfs排列所有满足条件的可能就可以了。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1 << 10;
int ans;
vector<int> nums;//存放符合条件平方数,数字的状态
void check(LL x) {
int status = 0;//记录数字的状态,初始时全部标记为0
if (x == 0) status = 1;//标记最低位即第0位为1
while (x) {
//获取10进制个位上的数,1移位后与上一次的状态做与运算
//不为0说明个位上的数字已经被使用,则不记录,return
if ((status & (1 << (x % 10))) != 0) return;
//记录数字使用情况
status |= (1 << (x % 10)); //标记个位对应位置为1
x /= 10; //消掉个位
}
nums.push_back(status);
}
void dfs(int x, int y) {//从第x个合法数字往后取,当前组合状态为y
if (y == maxn - 1) {//组合可行,记录答案
ans++;
return;
}
for (int i = x; i < nums.size(); i++) {//枚举新加入数字的状态
if ((nums[i] & y) == 0) { //可以加入组合,去找下一个数字
dfs(i + 1,nums[i] | y);
}
}
}
int main() {
//枚举算出满足题意的平方数并存储其状态
for (LL i = 0; i <= 100000; i++) {
check(i * i);
}
//用深搜按顺序组合预处理出的平方数
dfs(0,0);
cout << ans << endl;
return 0;
}