1. 程式人生 > >數學期望+區間標記

數學期望+區間標記

syn with color ssis name max sca 取出 space

https://vjudge.net/contest/237352#problem/G

題意:有n個玩具,編號為1到n,其中編號為i的玩具價值為wi。有m個區間,其中第i個區間為[li,ri],隨機選取了3個互不相同的數i,j,k(1i<j<km),將所有足 max(li,lj,lk)xmin(ri,rj,rk)的編號為x的玩具取出,求取出的玩具的有價值之和的期望是多少。

解法:考慮每一個點,對結果的影響,如果一個點包括了x個區間,那麽,就有C(x,3)個w[i]在分子上,分母為C(m,3);所以最終的問題就是要求每個點所在的區間數,用區間標記的方法實現。註意不要爆long long。

註意判斷判斷結果為整數,分數,以及0的情況。

 1 //#include<bits/stdc++.h>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <string>
 7 #include <cmath>
 8 #include <cstdlib>
 9 #include <queue>
10 #include <stack>
11
#include <map> 12 #include <vector> 13 #include <set> 14 #include <bitset> 15 #include <iomanip> 16 #define ms(a, b) memset(a, b, sizeof(a)); 17 using namespace std; 18 typedef long long LL; 19 typedef pair<int, int> pii; 20 const int INF = 0x3f3f3f3f; 21 const int
maxn = 5e4 + 10; 22 const int MAXN = 2e4 + 10; 23 const double eps = 1e-8; 24 const int mod = 1e9 + 7; 25 int n, m; 26 int w[maxn], f[maxn]; 27 28 LL C(LL k) { 29 return k * (k-1) * (k-2) / 6; 30 } 31 32 LL gcd(LL a, LL b) { 33 while(b) { 34 LL tmp = a % b; 35 a = b; 36 b = tmp; 37 } 38 return a; 39 } 40 41 void solve() { 42 43 return ; 44 } 45 46 47 int main() { 48 #ifdef local 49 freopen("case.in", "r", stdin); 50 // freopen("case.out", "w", stdout); 51 #endif 52 // ios::sync_with_stdio(false); 53 // cin.tie(0); 54 int T; 55 scanf("%d", &T); 56 while(T--) { 57 scanf("%d%d", &n, &m); 58 for(int i = 1; i <= n; i++) 59 scanf("%d", &w[i]); 60 ms(f, 0); 61 for(int i = 0; i < m; i++) { 62 int l, r; 63 scanf("%d%d", &l, &r); 64 f[l]++; 65 f[r+1]--; 66 } 67 LL cnt = 0, up = 0; 68 for(int i = 1; i <= n; i++) { 69 cnt += f[i]; 70 if(cnt >= 3) up += w[i] * C(cnt); 71 } 72 LL down = C(m); 73 LL div = gcd(up, down); 74 if(div > 0) { 75 up /= div; 76 down /= div; 77 if(down == 1) printf("%lld\n", up); 78 else printf("%lld/%lld\n", up, down); 79 } 80 else printf("0\n"); 81 } 82 // solve(); 83 return 0; 84 }

數學期望+區間標記