Cqoi2015 編號 逆向思維,暴力列舉

2022-06-03 07:06:10 字數 2021 閱讀 3526

online judge:luogu-p4222

label:逆向思維,暴力列舉

你需要給一批商品編號,其中每個編號都是乙個7位16進製制數(由0~9, a-f組成)。為了防止在人工處理時不小心把編號弄錯,要求任意兩個編號至少有三個位置對應的數字不相同。第乙個編號為0000000,第二個編號為不違反上述規定的前提下最小的編號,…,每次分配乙個新編號時,總是選擇不和前面編號衝突的最小編號(注意編號都是16進製制數,可以比較大小)。按此規律,前面若干編號分別是:0000000, 0000111, 0000222, …, 0000fff, 0001012, 0001103,0001230,0001321,0001456,…

輸入k,你的任務是求出第k小的編號

第一行為整數k。

輸出第k小的編號(字母必須輸出小寫)。輸入保證這個編號存在。

input

20
output

0001321
hint

對於30%的資料,\(k \leq 200\);

對於70%的資料,\(k \leq 10000\);

對於100%的資料,\(k \leq 200000\)。

第一眼以為二分答案,但是發現每個值都依賴於前面的數字。需要依次求解。

直接暴力列舉16進製制數,檢驗時,暴力與前面的數比較。

時間複雜度為\(o(ans+k^2*7)\)。其中從小到大列舉數字共\(ans\)次,每次檢驗時與前面的數字一位一位比較。

嘗試打表找規律,然後你會發現,除了最後兩個16進製制位規律比較迷之外,剩下的前面5位規律都是顯而易見的。所以直接打表後面兩個位(如果**長度限制允許的情況下),可以在o(1)時間內求解。

這個資料範圍顯然如果按剛才的方案去打表不太可行(但這題也有很多其他能夠ac的神奇打表+雜湊做法)。下面是一種比較簡潔的做法:

回到30分做法,顯然還是需要依次求解,那就嘗試優化後面的比較部分。採用逆向思維,當前數字與前面的數字比較,就算列舉都要o(n),不可做;那就嘗試用當前的數,對後面合法/不合法的數字打上標記

原題面:至少要有3個對應位不同,才合法

其實就是:只要存在至少5個對應位相同,就不合法

比較相同顯然比比較不同可做很多。對於當前弄到的乙個合法數字,我們利用組合,按順序挑出7個中的5個,將這個 組合\(mark\)了,注意,由於要控制對應位,還得記錄下這是\(c_7^5=21\)中的第幾個組合。

對應的,當判斷當前這個數字合不合法時,也是按順序挑出7個中的5個,如果被\(mark\)了則表示這個數字不合法;反之如果所有組合都沒被\(mark\)過,表示這個數字合法。

綜上,每次列舉時都可以在\(c_7^5\)的時間內判斷是否合法。

**如下:

#include#define for(a,b,c) for(a=b;a<=c;a++)

using namespace std;

int n,x[10],a,b,c,d,e,f;

bool mark[22][16][16][16][16][16];

inline void out(int c)

inline bool insert()

id=0;

for(a,0,6)for(b,a+1,6)for(c,b+1,6)for(d,c+1,6)for(e,d+1,6)

}int main()

}}

遞推 CQOI2015 選數

這個遞推實在是讓我感到無奈 實際上就是先計算出在l和r的區間中有多少個數有因數k 然後 f i 表示的就是在l和r中選出n個數最大公因數是i k 的方案數 然後 ll ll n l 1 i 1 ll rr n r i ll len rr ll 1 這幾句話的意思就是算出在n l 和 n r的範圍內有...

題解 CQOI2015選數

這題做的時候接連想錯了好多次 但是回到正軌上之後依然是乙個套路題。不過這題好像有比莫比烏斯反演更好的做法,莫比烏斯反演貌似是某種能過的暴力 不過能過也就行了吧哈哈。首先我們把數字的範圍要進行縮小 最大公約數為 k 那自然所有選出來的數都必須是 k 的倍數。所以我們改選數為選擇是 k 的多少倍。然後由...

cqoi2015部分題解

只做了前三題。t1 選數 先把題目轉化為求選n個數最大公約數為1,不用說了。假定f i 為選出n個數最大公約數為i的方案數。由於題目中有條件h l 10 5,所以i 10 5即可。令l l 1 i,r h i f i r l n sigma f a i r l 最後的r l為減去全部選擇乙個數的方案...