湊平方數 - 藍橋杯2016

湊平方數

把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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章