拯救l o n g m m ( l a n . p a s / c / c p p )
【題目描述】
longdd 將軍為了平息延續數年戰亂,決定釋放戰俘營中所有的俘虜。然而,
longdd 將軍不打算釋放敵軍的統帥longmm——因為這個傢伙異常聰明,是個難纏的
對手。所以longdd 將軍決定把longmm 用鍊子固定到牆上。鍊子由n 個環組成,每
個環有可能在牆上,也可能不在牆上。
「longdd 將軍,你為什麼把我綁在牆上,不讓我獲得自由」,longmm 咆哮道。
「但是,longmm,你並沒有被綁在牆上。我很確定你可以自己把鍊子解開」,
longdd 將軍回答道,「但是請你在天黑之前解開,否則我會因為你製造噪音把你重
新抓起來。」
請幫助longmm 吧!鍊子由n 個環組成,編號為1,2,…,n。我們可以把每個環從
牆上取下來或者從新放回牆上,但是需要遵循如下規則:
- 每一步只能取下或者裝上乙個環
- 編號為1 的環可以隨意取下或裝上
- 如果編號為1,…,k-1 的環都取下了,並且編號為k 的環在牆上,我們可
以隨意取下或者裝上第k+1 個環
- 當所有環都取下來之後,longmm 可以逃脫了
給定每個環的初始狀態,請你編寫程式計算longmm 最少需要多少步才能逃脫。
程式名: lan
【輸入格式】
* 第 1 行: 有乙個整數n,(1<=n<=1000),表示環的個數
* 第 2 行: 有n 個整數,第i 個整數o_i=0,表示第i 個環在初始的時候為摘下的
狀態;如果o_i=1,表示第i 個環初始的時候為裝在牆上的狀態。
【輸入樣例】
41 0 1 0
【輸出格式】
* 第 1 行: 只有乙個整數,表示最少需要多少步才能讓longmm 逃脫。
【輸出樣例】
6【輸出解釋】
先遞推
然後 找規律 發現從後往前 ans=2^jn-2^j(n-1)+2^j(n-2)+..... (j[i]表示從左往右第i個1)
program lan;
type
arr=record
len:longint;
d:array[1..1000] of longint;
end;
const
f=1000000;
var n,i:longint;
ans:arr;
p2:array[1..1000] of arr;
a:array[1..1001] of longint;
procedure multipy;
var i,j,k:longint;
begin
for k:=2 to 1000 do
begin
p2[k].len:=p2[k-1].len;
for i:=1 to p2[k-1].len do
begin
inc(p2[k].d[i],p2[k-1].d[i]*2);
inc(p2[k].d[i+1],p2[k].d[i] div f);
p2[k].d[i]:=p2[k].d[i] mod f;
end;
if p2[k].d[p2[k].len+1]<>0 then inc(p2[k].len);
end;
for k:=1 to 1000 do dec(p2[k].d[1]);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure add(a,b:arr;var c:arr);
var i,j:longint;
begin
fillchar(c,sizeof(c),0);
c.len:=max(a.len,b.len);
for i:=1 to c.len do
begin
inc(c.d[i],a.d[i]+b.d[i]);
inc(c.d[i+1],c.d[i] div f);
c.d[i]:=c.d[i] mod f;
end;
if c.d[c.len+1]>0 then inc(c.len);
end;
procedure sub(a,b:arr;var c:arr);
var i,j:longint;
begin
fillchar(c,sizeof(c),0);
c.len:=max(a.len,b.len);
for i:=1 to c.len do
begin
inc(c.d[i],a.d[i]-b.d[i]);
if c.d[i]<0 then
begin
inc(c.d[i],f);
dec(c.d[i+1],1);
end;
end;
while (c.len>1) and (c.d[c.len]=0) do dec(c.len);
end;
procedure work;
var i,j:longint;
flag:boolean;
begin
i:=n;
flag:=true;
while true do
begin
while (a[i]=0) and (i>1) do dec(i);
if a[i]=0 then exit;
if flag then add(ans,p2[i],ans)
else sub(ans,p2[i],ans);
dec(i);
if i=0 then exit;
flag:=not(flag);
end;
end;
procedure pri;
var i:longint;
begin
write(ans.d[ans.len]);
for i:=ans.len-1 downto 1 do
begin
if ans.d[i]<100000 then write('0');
if ans.d[i]<10000 then write('0');
if ans.d[i]<1000 then write('0');
if ans.d[i]<100 then write('0');
if ans.d[i]<10 then write('0');
write(ans.d[i]);
end;
writeln;
end;
begin
assign(input,'lan.in');
assign(output,'lan.out');
reset(input);
rewrite(output);
read(n);
for i:=1 to n do read(a[i]);
fillchar(ans,sizeof(ans),0);
fillchar(p2,sizeof(p2),0);
p2[1].len:=1;
p2[1].d[1]:=2;
multipy;
work;
pri;
close(input);
close(output);
end.
簡單遞推公式轉換矩陣求解
對於許多遞推題目,由於資料範圍太大直接迴圈寫會爆掉,這時首先想到的就是矩陣優化,把遞推式轉換成01矩陣通過快速冪優化。比如最簡單的斐波納挈,如果n非常大,迴圈遞推肯定是不合適的,那麼可以考慮下面的公式 f n f n 1 f n 1 f n 2 a 這裡的a是乙個01矩陣,此時的a 2 2的矩陣,可...
華為機試 放蘋果(遞推公式求解)
題目描述 把m個同樣的蘋果放在n個同樣的盤子裡,允許有的盤子空著不放,問共有多少種不同的分法?用k表示 5,1,1和1,5,1 是同一種分法。輸入每個用例包含二個整數m和n。0 m 10,1 n 10。樣例輸入 7 3樣例輸出 public static int count int m,int n ...
校內模擬 拯救(遞推)
這題年代可久遠了。似乎是今年寒假還是什麼時候loli的測試題來著?反正atp當時太水了不會做。現在越看越覺得當時很蛋疼 不過看這個題目的話,首先它的目標狀態是把所有的都變成0,所以會有乙個f i 表示把前i個都變成0所需要的最少步數 其次,它要改變第i個點的狀態一定是把前i 2個變成0並且把第i 1...