【問題描述】
乙個集合有如下元素: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] oflongint;
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位 輸入資料均不需判...