凑平方数
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。 比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...
注意,0可以作为独立的数字,但不能作为多位数字的开始。 分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
注意:需要提交的是一个整数,不要填写多余内容。
答案: 300
注意了 官方答案是300!不是某个差一点(由于 int 没改成 ll )拿国一的博主说的 !正确答案 263 !!!
网上有的博主用的JAVA大整数做的 那么我就用C++ 暴力来写吧
思路:
通过next_permutation() 进行”0123456789“ 的全排列
然后对每一个排列都扫描一下,看能不能分成几个平方数
扫描通过 dfs来实现
每层dfs处理自己得到的串时
从 pos 位置(每层dfs 的串开始位置)开始 取一个 或者俩个,三个,四个......取全部,然后把剩下的交给下一个dfs
然后判断这几个数字组成的数能否开方,是继续,否则跳过。
嘛~~~ 说起来简单........
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <set>
using namespace std;
int num = 0;
// 通过 东东学长教的 set神器 来查重 (有点硬核。。。)
set< set<int> > vs;
void dfs(string s,int pos,set<int> ss){
if(pos == 10){
vs.insert(ss);
num++;
}
int len = s.size();
long long sum = 0;
for(int i=pos;i<len;++i){
//把从 s[pos-i] 变为整数
sum*=10;
sum+=(s[i]-'0');
// 看是不是可以开方
double x = sqrt(sum);
// 如果第一个是0且长度为 1 或者 第一个不为0 是个能被开方的数
if( (s[pos] =='0'&& i == pos) || (s[pos]!='0' && x == double((long long)(x))) ) {
ss.insert(sum);
dfs(s,i+1,ss);
ss.erase(sum);
}
}
}
int main(){
// 来一次全排列!
string s="0123456789";
set<int> ss;
do{
//每次都把这次排列扫一遍
dfs(s,0,ss);
}while(next_permutation(s.begin(),s.end()));
cout<<vs.size()<<endl;
cout<<num<<endl;
return 0;
}