题目
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
0 1 4 5 6 9
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
思路
首先用全排列,将每一个排列组合弄出来,然后dfs,在每一个排列当中,找出可行的分法(注意:同一个排列当中可能会有不同的分法),所以,我们在每一种分法里面,每一个平方数后面加一个‘,’,表示不同的分法。同一个排列当中,逗号个数或位置不同,那么就是不同的分法。最后存到set里面,利用set自动去重的特点,直接输出q.size()。
知识点
全排列函数、深搜、集合
代码
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
ll num[20],tmp[20],ans=0;
int a[10]={0,1,2,3,4,5,6,7,8,9};
set<string> q;
bool judge(ll x)//判断是否是平方数
{
return (ll)sqrt(x)*(ll)sqrt(x)==x;
}
void dfs(int pos,int cnt)
{
if(pos==10)
{
string s="",t="";
for(int i=0;i<cnt;i++)
tmp[i]=num[i];
sort(tmp,tmp+cnt);//排序
for(int i=0;i<cnt;i++)
{
t="";
ll x=tmp[i];
if(x==0)
t+='0';
while(x)
{
t+=(x%10)+'0';
x/=10;
}
reverse(t.begin(),t.end());//倒序给的t,所以再反过来
s+=t;
s+=',';
}
q.insert(s);
return ;
}
if(a[pos]==0)//0不能作为某个数的开头
{
num[cnt]=0;
dfs(pos+1,cnt+1);
return ;
}
ll sum=0;
for(int i=pos;i<10;i++)
{
sum=sum*10+a[i];
if(judge(sum))
{
num[cnt]=sum;
dfs(i+1,cnt+1);
}
}
}
int main()
{
do
{
dfs(0,0);
}while(next_permutation(a,a+10));
cout<<q.size()<<endl; //q的大小就是答案
return 0;
}