湊平方數
把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;
}