题目描述
题目来源:2016蓝桥杯国赛
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
把 0 ~ 9 这 10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:
0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
...
注意,0 可以作为独立的数字,但不能作为多位数字的开始。 分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
思路:
1. 先生成 9876543210(因为这个数是0-9这十个数字组成的最大的数)已内的平方数且平方数不能含有相同的数字,用动态数组v保存;
2. 平方数中是否含有相同的数字可以使用二进制“与”运算来判断,不含相同数字的平方数可以用 一个10位的二进制数status来表示;
3. 使用dfs来寻找刚好可以凑够0-9这个十个数字的平方数的组合;
//2016g 凑平方数
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include <set>
vector<long long> v;
void abc(long long x) //判断n中是否有重复数字
{
int status=0;
if(x==0) status=1;
while(x)
{
if((status&(1<<(x%10)))!=0) return ; //数字有重复
status|=(1<<(x%10)); //更新包含数字的状态
x/=10;
}
v.push_back(status); //status 保存的是平方数的状态
}
void create_pingfangshu() //创建平方数数组v
{
long long i,t;
for(i=0;;i++)
{
t=i*i;
if(t>9876543210) break;
abc(t);
}
}
int ans=0;
void dfs(int x,int y) //dfs剪枝 ,x表示从第x个合法数字开始取,y表示当前组合的状态
{
if(y==(1<<10)-1) //y==十个一,满足题目要求(即0~9每个使用一次)
{
ans++;return ;
}
for(int i=x;i<v.size();i++)
{
if((v[i]&y)==0) //v[i]与已存状态没有共同数字
{
dfs(i+1,v[i]|y); //当前取的是第i个,下次从i+1开始取;
}
}
}
int main()
{
int i;
create_pingfangshu();
dfs(0,0);
cout<<ans<<endl;
return 0;
}