HDU 5419
题目链接:
题意:
给一个长度为n的序列,给m个区间。
问任意取三个区间,取三个区间中左端点最大值,右端点最小值,然后把这个区间(闭区间)的权值加起来,这样权值的期望是多少。
思路:
水题,统计到第几个数的时候在几个区间中。设在k个区间中,则总期望+=C(k,m)
现场赛的时候看到此题已晚。一般不贴会做的题,然而有一处TLE至今没想明白所以贴上。估计是数据过大爆了long long,然后负数的gcd无解。
源码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <ctime>
#include <climits>
#include <cassert>
#include <cmath>
#include <string>
#include <bitset>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <functional>
#include <utility>
#include <numeric>
#define LL long long
#define gmax(a,b) ((a) > (b) ? (a) : (b))
#define gmin(a,b) ((a) < (b) ? (a) : (b))
#define MOD (1000000007)
//#define gcd(a,b) __gcd(a,b)
using namespace std;
const int MAXN = 50000 + 5;
int suml[MAXN], sumr[MAXN];
int val[MAXN];
int n, m;
LL gcd(LL a, LL b)
{
if(a < b)
return gcd(b, a);
if(b == 0)
return a;
return gcd(b, a % b);
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(int i = 1 ; i <= n ; i++)
scanf("%d", &val[i]);
memset(suml, 0, sizeof(suml));
memset(sumr, 0, sizeof(sumr));
for(int j = 0 ; j < m ; j++){
int u, v;
scanf("%d%d", &u, &v);
suml[u]++;
sumr[v]++;
}
LL ans = 0;
int tsum = 0;
for(int i = 1 ; i <= n ; i++){
tsum += suml[i];
tsum -= sumr[i - 1];
// printf("i = %d, tsum = %d\n", i, tsum);
if(tsum >= 3){
// printf("val[i] = %d, n = %d\n, tsum = %d\n", val[i], n, tsum);
ans += val[i] * 1LL * (tsum) * (tsum - 1) / 2 * (tsum - 2) / 3;///这里也是哦~同下
}
}
LL t2 = m * 1LL * (m - 1) / 2 * (m - 2) / 3;///这里不除以2和3会T,shenmegui
if(m <= 2 || ans == 0){
printf("0\n");
continue;
}
LL g = gcd(ans, t2);
ans /= g;
t2 /= g;
if(t2 == 1)
printf("%I64d\n", ans);
else
printf("%I64d/%I64d\n", ans, t2);
}
return 0;
}