集合刪數 (vijos 1545) 題解

2021-07-09 09:34:38 字數 1781 閱讀 4358

【問題描述】

乙個集合有如下元素:1是集合元素;若p是集合的元素,則2 * p +1,4*p+5也是集合的元素,取出此集合中最小的k個元素,按從小到大的順序組合成乙個多位數,現要求從中刪除m個數字上的數字,使得剩下的數字最大,程式設計輸出刪除前和刪除後的多位數字。

注:不存在所有數被刪除的情況。

5 4137915 95

首先,我們可以將該問題轉化為兩個子問題:

1:求2*p+1與4*p+5兩個集合中前k個數組成的數。

2:求如何刪去m個數字使留下的數最大,並輸出該數。

對於子問題1,其實是很好辦的,直接將兩個集合轉化為兩個佇列,取走兩個佇列中更小的隊首元素,並將其擴充套件放入到兩個集合中,直到取出了k個數。

那麼關鍵在於如何解決子問題2。

既然要使留下的數最大,那麼自然是越高位越大越好,於是,對於某乙個數字是取還是舍,我們應遵循下面兩個原則:

1:如果該數字比其之前的數字大,那麼我們應盡量捨去之前的數字。

2:如果捨去的數字已經有m個了,那就不必捨去了。

因此,對於每乙個數字,我們應把它與它前面的數字進行比較,如果滿足上述兩個原則,那麼就取代其之前的數。詳見**。

var t,k:array[1..200000] of

longint;

sta:

array[0..200000] of

char;

t1,t2,i,n,m,l,top,r1,r2:longint;

s,st:ansistring;

begin

readln(n,m);

i:=1

; t[

1]:=3

; k[

1]:=9

; t1:=1

; t2:=1

; r1:=1

; r2:=1

; s:='1'

; while ido

if t[r1]then

begin

inc(i);

str(t[r1],st);

s:=s+st;

inc(t1);

t[t1]:=2*t[r1]+1

; inc(t2);

k[t2]:=4*t[r1]+5

; inc(r1);

endelse

begin

inc(i);

str(k[r2],st);

s:=s+st;

inc(t1);

t[t1]:=2*k[r2]+1

; inc(t2);

k[t2]:=4*k[r2]+5

; inc(r2);

end; writeln(s);//解決子問題1

l:=length(s);

m:=l-m;

sta[

0]:=chr(57

); top:=1;

for i:=1

to l do

begin

while(s[i]>sta[top-1])and(top+l-i>m)do//滿足兩個原則,取代

dec(top);

sta[top]:=s[i];

inc(top);

end;

for i:=1

to top-1

doif sta[i]<>'0'

then

break;//注意:前導0不要輸出

for i:=i to m do

write(sta[i]);

writeln;

end.

刪數問題 題解

本題使用貪心思想 乙個讓這串數字越小,它的高位數就得越小。我們每次刪除要使得刪除後的數高位盡量的小。每一次刪除時,從最高位開始向低位數遍歷,當遇到的一位數比它的更高位更小時,我們就刪除它的更高一位,讓這個更小的數 篡位 就可以保證這串數更小。下一次刪除時,要也從新從最高位開始。需要注意的地方 刪除了...

集合選數題解

構造神題,對於每乙個不含質因數2和3的數字,我們構造乙個矩陣 可能並不滿 第一行第一列是這個數,在同一行中,下一列的數是這一列的數的2倍,在同一列中,下一行的數是這一行的數的3倍。如果我們選矩陣中乙個數,則右邊的數是這個數的兩倍而不能選,同理,下面的數同樣不能選,不能選左邊的數,因為這個數是它的兩倍...

題解 刪數問題 Noip1994

時間限制 1000 ms 記憶體限制 65536 kb 提交數 11506 通過數 3852 輸入乙個高精度的正整數n,去掉其中任意s個數字後剩下的數字按原左右次序組成乙個新的正整數。程式設計對給定的n和s,尋找一種方案使得剩下的數字組成的新數最小。輸出新的正整數。n不超過240位 輸入資料均不需判...