日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[NOI2007] 货币兑换 (dp+李超树维护凸包)

發布時間:2023/12/3 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [NOI2007] 货币兑换 (dp+李超树维护凸包) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

description

小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 的變化分別為:

假定在第一天時,用戶手中有 100元 人民幣但是沒有任何金券。用戶可以執行以下的操作:

注意到,同一天內可以進行多次操作。小Y是一個很有經濟頭腦的員工,通過較長時間的運作和行情測算,他已經知道了未來N天內的A券和B券的價值以及Rate。他還希望能夠計算出來,如果開始時擁有S元錢,那么N天后最多能夠獲得多少元錢。

Input
輸入第一行兩個正整數N、S,分別表示小Y能預知的天數以及初始時擁有的錢數。接下來N行,第K行三個實數AK、BK、RateK,意義如題目中所述
對于100%的測試數據,滿足:0<AK≤10;0<BK≤10;0<RateK≤100;MaxProfit≤0^9。
【提示】
1.輸入文件可能很大,請采用快速的讀入方式。
2.必然存在一種最優的買賣方案滿足:
每次買進操作使用完所有的人民幣;
每次賣出操作賣出所有的金券。

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

Sample Input
3 100
1 1 1
1 2 2
2 2 3
Sample Output
225.000
Hint

solution

乍一看跟以前做過的股票交易挺像的,這個式子長得就斜率優化誘惑


Step1
貪心。。。
在某一天要么買股票把錢買完,要么賣股票把股票賣完
不會有人賺錢只賺一半就跑了吧


Step2
考慮列出狀態轉移方程
fif_ifi?表示iii天能賺的最多的錢,aia_iai?iii天最多能買的AAA股票數,bib_ibi?iii天最多能買的BBB股票數
①在iii天買入股票ai=fi×RateiAi×Ratei+Bi,bi=fiAi×Ratei+Bia_i=\frac{f_i\times Rate_i}{A_i\times Rate_i+B_i},b_i=\frac{f_i}{A_i\times Rate_i+B_i}ai?=Ai?×Ratei?+Bi?fi?×Ratei??,bi?=Ai?×Ratei?+Bi?fi??
②在iii天不買不賣
fi=max(fi,fi?1)f_i=max(f_i,f_{i-1})fi?=max(fi?,fi?1?)
③在iii天賣股票,枚舉在jjj天買入的股票
fi=max{aj?Ai+bj?Bi}f_i=max\{a_j*A_i+b_j*B_i\}fi?=max{aj??Ai?+bj??Bi?}
對式子進行變形
fi=max{Bi×(AiBi?aj+bj)}f_i=max\{B_i\times (\frac{A_i}{B_i}*a_j+b_j)\}fi?=max{Bi?×(Bi?Ai???aj?+bj?)}


Step3
李超線段樹維護凸包
fif_ifi?的式子看作直線kx+bkx+bkx+b
k=aj,x=AiBi,b=bjk=a_j,x=\frac{A_i}{B_i},b=b_jk=aj?,x=Bi?Ai??,b=bj?

code

#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define maxn 100005 int n; double ans; double A[maxn], B[maxn], Rate[maxn], c[maxn], x[maxn], k[maxn], b[maxn]; int t[maxn << 2];double calc( int i, int pos ) {return k[i] * x[pos] + b[i]; }void modify( int num, int l, int r, int id ) {if( l == r ) {if( calc( id, l ) > calc( t[num], l ) ) t[num] = id;return;}int mid = ( l + r ) >> 1;if( calc( id, mid ) > calc( t[num], mid ) ) swap( t[num], id );if( calc( id, l ) > calc( t[num], l ) ) modify( num << 1, l, mid, id );if( calc( id, r ) > calc( t[num], r ) ) modify( num << 1 | 1, mid + 1, r, id ); }double query( int num, int l, int r, int pos ) {if( l == r ) return calc( t[num], pos );int mid = ( l + r ) >> 1;if( pos <= mid ) return max( calc( t[num], pos ), query( num << 1, l, mid, pos ) );else return max( calc( t[num], pos ), query( num << 1 | 1, mid + 1, r, pos ) ); }int main() {scanf( "%d %lf", &n, &ans );for( int i = 1;i <= n;i ++ ) {scanf( "%lf %lf %lf", &A[i], &B[i], &Rate[i] );x[i] = c[i] = A[i] / B[i];}sort( x + 1, x + n + 1 );for( int i = 1;i <= n;i ++ ) {int p = lower_bound( x + 1, x + n + 1, c[i] ) - x;ans = max( ans, B[i] * query( 1, 1, n, p ) );double g = A[i] * Rate[i] + B[i];k[i] = ans * Rate[i] / g, b[i] = ans / g;modify( 1, 1, n, i );}printf( "%.3f\n", ans );return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的[NOI2007] 货币兑换 (dp+李超树维护凸包)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。