数学题 贪心+二分答案
生活随笔
收集整理的這篇文章主要介紹了
数学题 贪心+二分答案
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
現在有兩個數組?AA?和?BB, 分別包含?xx?與?yy?個元素。
定義一個新的數組?CC,?CC?中包含?x×yx×y?個元素,為?AA?中所有元素除以?BB?中所有元素。
即 新集合為?{c∣c=ab,a∈A,b∈B}{c∣c=ab,a∈A,b∈B}?。特殊地,CC?為多重集合。
請求?CC?數組的第?kk?大數。
Input
第一行一個整數?TT(T≤3T≤3)表示方案數。
對于每個方案:
第一行三個整數?n,m,kn,m,k(0<n,m≤100000,0<k≤n×m0<n,m≤100000,0<k≤n×m?)
第二行?nn?個正整數;
第三行?mm?個正整數。
數組中元素?<108<108。
Output
對于每個方案,輸出一行:
數組?CC?的第?kk?大數。結果四舍五入到兩位小數。
Sample Input
2 5 5 3 1 2 3 4 5 2 3 4 5 6 5 5 2 1 2 3 4 5 2 3 4 5 6Sample Output
1.67 2.00 題解:這個題乍一看想FFT,其實沒有那么麻煩,只是個簡單的二分答案。如果一個數是第K大的數,那么一定存在至少K個數小于等于它,把這個作為二分的條件。
如何判斷有K個數小于等于它呢,好像不是很好判斷,我們轉換為計算大于x的數的個數。
我們可以把A數組和B數組排序,然后用雙指針,指針Pa指向數組A的左端,指針Pb指向數組B的左端,這樣固定Pa,把Pb像右移動,直到(*Pa)/(*Pb) < x為止,然后Pa向右移動一個,再循環這個操作,直到Pa到頭或者Pb到頭(可以證明Pb始終不需要掉頭)
check函數的代碼:
int check(double x) {int tot = 0;int pos = 0; for(int i = 0;i < N;i++){while(pos < M && (double)A[i]/(double)B[pos] >= x) pos++;tot += pos;}return tot; }代碼: #include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int MAX = 100005; const double EPS = 0.001; int A[MAX],B[MAX]; int N,M,K; int check(double x) {int tot = 0;int pos = 0; for(int i = 0;i < N;i++){while(pos < M && (double)A[i]/(double)B[pos] >= x) pos++;tot += pos;}return tot; } int main() {int T;scanf("%d",&T);while(T--){scanf("%d%d%d",&N,&M,&K) ;for(int i = 0;i < N;i++) scanf("%d",&A[i]);for(int i = 0;i < M;i++) scanf("%d",&B[i]);sort(A,A + N);sort(B,B + M);double l = 0,r = A[N-1];while(r - l > EPS){double mid = (r + l) /2;if(check(mid) < K) r = mid;//檢查大于mid的數有多少個 else l = mid; }printf("%.2f\n",l);}return 0;} /*2 5 5 3 1 2 3 4 5 2 3 4 5 6 5 5 2 1 2 3 4 5 2 3 4 5 6*/
總結
以上是生活随笔為你收集整理的数学题 贪心+二分答案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公共子串 字符串哈希
- 下一篇: 李贺的雅号是什么 李贺的雅号是诗鬼