把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
注意:需要提交的是一个整数,不要填写多余内容。
这道题目并不难想,获得这10个数的全排列,然后将这10个数进行划分,最后去重即可
思路:
1.先打表,用于判断一个数是不是平方数,至于为什么不用sqrt( )这个函数,主要是这个函数返回值是double类型,数字类型转换的时候怕出现精度丢失引起的错误
2.用algorithm下的next_permutation( )函数生成全排列
3.深搜,对这个序列进行划分,注意一点,划分后的各组数字是不能以0为起始数字(除非是单个0),可以通过判断数字位数来解决
4.去重,将划分好的数字序列排序之后生成字符串(stringstream的作用,感兴趣的同学可以看一下),map判断是否出现过,我选择将一个序列的数字之间加上空格之后的得到字符串作为去重标准(为什么要这么做?举个例子 0,1,2345,6789(假设这是一个合法的序列)0,1,234,567,89(假设这是也一个合法的序列),那么同一个序列可能有多种划分方法,加上空格作为间隔,就可以将它们区分,如果结果是294,295之类的可以这么试试)
5.这个程序在我的电脑上运行的挺慢的(毕竟复杂度在那里)
300
--------------------------------
Process exited after 48.16 seconds with return value 0
请按任意键继续. . .
#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<cmath>
#include<map>
using namespace std;
int an[10]={0,1,2,3,4,5,6,7,8,9},cnt=0;
long long bn[10];
map<long long,int> lli;
map<string,int> si;
void dfs(int pos,int len,int next)
{
if(len==10)
{
string str="";
long long cn[10]={0};
for(int i=0;i<next;i++)
cn[i]=bn[i];
sort(cn,cn+next);
for(int i=0;i<next;i++)
{
stringstream stream;
string tmp;
stream << cn[i];
stream >> tmp;
str+=tmp;
str+=" ";
}
if(si[str]==0)
{
si[str]=1;
//cout << str << endl;
cnt++;
}
return ;
}
long long t=0;
for(int i=len;i<10;i++)
{
t=t*10+an[i];
if(t==0)
{
bn[next]=t;
dfs(i+1,len+i-pos+1,next+1);
}
else if(lli[t]==1&&(int)log10(t)==i-pos)
{
bn[next]=t;
dfs(i+1,len+i-pos+1,next+1);
}
}
}
int main()
{
for(long long i=0;i<100000;i++)
lli[i*i]=1;
do
{
dfs(0,0,0);
}while(next_permutation(an,an+10));
cout << cnt;
return 0;
}