NOI2007 貨幣兌換

2022-06-02 10:03:09 字數 3231 閱讀 9702

【問題描述】

小 y最近在一家金券交易所工作。該金券交易所只發行交易兩種金券:a紀念券(以下簡稱a券)和b紀念券(以下簡稱b券)。每個持有金券的顧客都有乙個自己的 帳戶。金券的數目可以是乙個實數。每天隨著市場的起伏波動,兩種金券都有自己當時的價值,即每一單位金券當天可以兌換的人民幣數目。我們記錄第k天中a券 和b券的價值分別為ak和bk(元/單位金券)。

為了方便顧客,金券交易所提供了一種非常方便的交易方式:比例交易法。

比例交易法分為兩個方面:

a)賣出金券:顧客提供乙個[0,100]內的實數op作為賣出比例,其意義為:將op%的a券和op%的b券以當時的價值兌換為人民幣;

b)**金券:顧客支付ip元人民幣,交易所將會兌換給使用者總價值為ip的金券,並且,滿足提供給顧客的a券和b券的比例在第k天恰好為ratek;

例如,假定接下來3天內的ak、bk、ratek的變化分別為:

時間ak

bkratek

第一天111

第二天122

第三天223

假定在第一天時,使用者手中有100元人民幣但是沒有任何金券。

使用者可以執行以下的操作:

時間使用者操作

人民幣(元)

a券的數量

b券的數量開戶無

1000

0第一天

**100元050

50第二天

賣出50%

7525

25第二天

**60元

1555

40第三天

賣出100%

2050

0注意到,同一天內可以進行多次操作。

小y是乙個很有經濟頭腦的員工,通過較長時間的運作和**測算,他已經知道了未來n天內的a券和b券的價值以及rate。他還希望能夠計算出來,如果開始時擁有s元錢,那麼n天後最多能夠獲得多少元錢。

【輸入格式】

第一行兩個正整數n、s,分別表示小y能預知的天數以及初始時擁有的錢數。接下來n行,第k行三個實數ak、bk、ratek,意義如題目中所述。

【輸出格式】

只有乙個實數maxprofit,表示第n天的操作結束時能夠獲得的最大的金錢數目。答案保留3位小數。

正解=動歸+平衡樹

考慮簡單dp

狀態:設f[i]為第i天能賺的最多錢為多少

方程:f[i]=max(f[i-1],na*a+nb*b)(j< i)

(na,nb為第j天能換到的a劵數量和b劵數量)

考慮優化:

設 na 為 x,nb 為 y

則sum=x*a+y*b 既 y = -a/b*x+sum/b

由於a,b為定值

sum的max以 -a/b 為斜率的過點(x,y)的截距的max*b

顯然可能得到max解截距的點必然是個上凸殼

建立以x為關鍵字的平衡樹維護值(其實很簡(dan)單(teng))

由於在樹上的點對映的截距具有單調性,

找最大值是便可通過平衡樹的前驅後繼判斷max在左子樹或右子樹;

**如下:

1 #include2 #include3 #include4 #include

5 #include6 #include7

#define inf 99999999

8#define ll long long

9#define cint(o) const int o=0

10#define cdou(o) const double o=0

11#define min(num1,num2) if(num1>num2) num1=num2

12#define max(num1,num2) if(num113

struct

tree

18 }a[100010

];19

introot,total,n;

20const

long

double o=1e-8;21

void cal(double sum,double a,double b,double k,double &na,double &nb)

25void rig(int

now)

3536

void lef(int

now)

46double

cross(tree a,tree b,tree c)

50void splay(int now,int f=0)64

if(!f) root=now;65}

6667

void

creat()

75int prev(int

now)

81int succ(int

now)

87void del(int start,int now,int

end)

93void maintain(int

now)

100while(1

)109

while(1

)118

}119

void insert(double x,double

y)126

if(a[now].x-x>o)

127if

(a[now].l)

128 now=a[now].l;

129else

137else

138if

(a[now].r)

139 now=a[now].r;

140else

149}

150}

151double fo(tree now,double

k)154

int pre(int

now)

160161

int suc(int

now)

167double slove(double

k)173

if(now==2

)177

178if

(a[now].l)

184}

185if

(a[now].r)

191}

192return

fo(a[now],k);

193194

}195

} 196

intmain()

210 printf("

%.3lf

",s);

211 }

view code

NOI2007 貨幣兌換

今天聽了crazy和samjia的noi雜 砸 題選講,感覺自己萌萌噠 於是就來怡情地寫了這道題。額 o 這個不好說啊。語文不好不好裱我 還是貼圖吧。咳咳,希望大家都看懂題了。乙個很明顯的貪心思路就是,我們每天要不全買,要不全賣。因為一有利益我們就去佔,一有虧損我們就不碰。那麼我們可以有dp方程 f...

Noi2007 貨幣兌換

傳送門 小半個上午 一下午都給了這題了qaq 都知道是斜率優化,問題是我看這題根本就是乙個人乙個式子啊 算了,把我的過程列出來吧 令 f i 表示第i天結束時強制賣出所有金券最多能得到的軟妹幣數量,列舉上一次 金券的時間,就有 beginf i max end 這裡沒有寫隱含條件 f i ge f ...

NOI2007 貨幣兌換

題目 先來畫一畫柿子 設 dp i 表示你第 i 天之後最多剩下多少錢 考慮一下對於 i 的轉移,我們肯定要在之前列舉一天 j 這一天把所有的東西買進來,之後在 i 天賣掉 設那天買進 a 的量為 d a 買進 b 的量為 d b 我們可以得到這樣的方程 d ap a d bp b dp j d a...