凑平方数
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等…
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
注意:需要提交的是一个整数,不要填写多余内容。
答案
300
技巧:用int的后10为储存当前状态有哪些数字已经出现(mask蒙版),
在对平方数从大到小打表的时候直接记录这个数字的mask,这样在dfs选数的时候可以直接蒙版间的或运算,得到是否有数字重复。递归时可以直接与运算,叠加蒙版状态。
#include <iostream>
#include<vector>
const int ligal = 0b1111111111;
using namespace std;
int a[10];
vector<int>num;
long long ans;
void dfs(int k, int mask) {
if (mask == ligal) {
ans++;
return;
}
for (int i = k; i < num.size(); ++i) {
if ((mask & num[i]) == 0) {
dfs(i + 1, mask | num[i]);
}
}
}
void f(long long k) {
int mask = 0;
if(k)
while (k) {
int t = 1 << k % 10;
if (mask & t)return;
mask |= t;
k /= 10;
}
else {
mask = 1;
}
num.push_back(mask);
return;
}
int main()
{
long long i, j;
int t = sqrt(9876543210);
for (i = 0;i<t; ++i) {
f(i * i);
}
int mask = 0;
dfs(0,mask);
cout << ans;
return 0;
}