基礎演算法題 帶分數(全排列,工具庫)

2021-10-04 08:05:03 字數 3486 閱讀 8481

前言

這道題理解起來不難,但是要找到乙個合適的方法對題目進行優化,就會相對麻煩些。

藍橋杯的題,真的到處都是坑的感覺。。。

資源限制

時間限制:1.0s 記憶體限制:256.0mb

問題描述

100 可以表示為帶分數的形式:100 = 3 + 69258 / 714。

還可以表示為:100 = 82 + 3546 / 197。

注意特徵:帶分數中,數字1~9分別出現且只出現一次(不包含0)。

類似這樣的帶分數,100 有 11 種表示法。

輸入格式

從標準輸入讀入乙個正整數n (n<1000*1000)

輸出格式

程式輸出該數字用數碼1~9不重複不遺漏地組成帶分數表示的全部種數。

注意:不要求輸出每個表示,只統計有多少表示法!

樣例輸入1

100樣例輸出1

11樣例輸入2

105樣例輸出2

6題目分析

①、帶分數中,數字1~9分別出現且只出現一次(不包含0)。

②、100 可以表示為帶分數的形式:100 = 3 + 69258 / 714。

解題思路

實用工具功能及使用

實現全排列:next_permutation(s.begin(), s.end());

在c++中,在字串要有序的前提下,我們能使用現成的函式完成字串的全排列。例如:string s=「123456789」;,字串s已經有序。通過 while(next_permutation(s.begin(), s.end())); 不斷將s進行全排序,當s的全排序全部排完後,跳出迴圈。可能你會覺得這個有什麼用?讓我們帶著這個問題看看**設計吧!

string s=

"123456789";do

while

(next_permutation

(s.begin()

, s.

end())

);

我們這裡用do-while的迴圈體,保證s每進行一次全排列就會先進行do包含的語句。

實現字串擷取:string a = s.substr(i,len);

在s字串中,從下標為i的位置,向右擷取len長度的字串,得到a字串。

實現字串轉換為int型別變數:int a = atoi(s.c_str);

將字串s轉換為int型別變數a。

**實現

**一通過我們的解題思路和工具結合,我們可以得到以下**一。

//全排列 next_permutation(s.begin(),s.end())

#include

#include

using namespace std;

#define ll long long

ll ans=0;

intmain()

}}//使用next_permutation前要先排序

while

(next_permutation

(s.begin()

, s.

end())

);cout<

// finish = clock();

// double _time = (double)(finish - start) / clocks_per_sec;

// printf("\ntime:%llf", _time);

return0;

}

好啦,恭喜你答對了題目一半,為什麼是一半呢?因為如果你拿去評測的話, 你會發現:執行超時!

下面是**二在n=100條件下的執行時間time (單位秒)

原因:substr函式返回的是值(而不是引用或指標) 在多次呼叫中傳遞了大量物件(而不是引用或指標) 導致了耗時多

在**裡,substr函式被放在內層迴圈中,被呼叫的次數很多,這樣的對程式執行總時間的影響就增大了,拖慢了程式執行速度。

**二(手寫擷取字串,引用字串s)

#include

#include

using namespace std;

#define ll long long

ll ans=0;

intparse

(string &s,

int a,

int b)

//字串轉換為int型別

return temp;

}int

main()

}}}while

(next_permutation

(s.begin()

, s.

end())

);cout<

// finish = clock();

// double _time = (double)(finish - start) / clocks_per_sec;

// printf("\ntime:%llf", _time);

return0;

}

優化:擷取字串函式傳參採用傳指標或引用(即在parse 的string引數右側加乙個&)。

下面是**二在n=100條件下的執行時間time (單位秒)

時間上滿足1s內,可以通過評測。

下面還能夠再通過優化演算法的方式,進一步縮短執行時間。

**三(演算法優化)

#include

#include

using namespace std;

#define ll long long

ll ans=0;

intparse

(string& s,

int a,

int b)

//字串轉換為int型別

return temp;

}int

main()

}}}while

(next_permutation

(s.begin()

, s.

end())

);cout<

// finish = clock();

// double _time = (double)(finish - start) / clocks_per_sec;

// printf("\ntime:%llf", _time);

return0;

}

優化:排除多餘判斷情況。

下面是**三在n=100條件下的執行時間time(單位秒)

總結這道題思路固然重要,但是優化也很重要。

在藍橋杯的比賽中,都是提交**,我們不能都提前判斷我們的**是否能夠通過所有評測資料,所以要盡量將時間複雜度降到最小。

希望能夠將自己的一些學習經驗分享給有需要的人。

我是小鄭,乙個堅持不懈的小白。

帶分數 全排列

100 可以表示為帶分數的形式 100 3 69258714 還可以表示為 100 82 3546197 類似這樣的帶分數,100 有 11 種表示法。輸入格式 乙個正整數。輸出格式 輸出輸入數字用數碼 1 9 不重複不遺漏地組成帶分數表示的全部種數。資料範圍 1 n 106 輸入樣例1 100輸出...

藍橋帶分數(全排列)

100 可以表示為帶分數的形式 100 3 69258 714 還可以表示為 100 82 3546 197 注意特徵 帶分數中,數字1 9分別出現且只出現一次 不包含0 類似這樣的帶分數,100 有 11 種表示法。題目要求 從標準輸入讀入乙個正整數n n 1000 1000 程式輸出該數字用數碼...

帶分數(全排列 判斷條件)

100 可以表示為帶分數的形式 100 3 69258 714 還可以表示為 100 82 3546 197 注意特徵 帶分數中,數字1 9分別出現且只出現一次 不包含0 類似這樣的帶分數,100 有 11 種表示法。題目要求 從標準輸入讀入乙個正整數n n 1000 1000 程式輸出該數字用數碼...