天天看点

Codeforces Round #341 (Div. 2) C. Wet Shark and Flowers(简单容斥)

题目链接:点击打开链接

题意:有n个人围坐成一圈,每个人可以从a[i].l 到 a[i].r里选一个数,如果相邻两个数的乘积能整除p,那么就奖励他们一人1000,求所得钱的总和的期望。

思路:既然求期望, 先求概率。 显然是要求每组相邻两个人的值乘积能否被p整除, 可以很容易知道在区间里有多少个数不能被p整除, 正难则反, 就能算出相邻两个有多少种组合不能被p整除, 那么也就很容易算出每组可以被p整除的概率, 乘上2000就是每组的期望, 期望加和就是总的期望。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 1000000000;
const int maxn = 100000 + 10;
int T,n,m,p;
struct node {
    int l, r, num;
    double p;
}a[maxn];
int main() {
    scanf("%d%d",&n,&p);
    for(int i=0;i<n;i++) {
        scanf("%d%d",&a[i].l,&a[i].r);
        a[i].num = a[i].r/p - (a[i].l - 1)/p;
    }
    double ans = 0;
    for(int i=0;i<n;i++) {
        int j = (i + 1) % n;
        double la = a[i].l, ra = a[i].r, lb = a[j].l, rb = a[j].r;
        double c1 = a[i].num, c2 = a[j].num;
        a[i].p = 1.0 - (double)(ra - la + 1 - c1)/(double)(ra - la + 1) * (double)(rb - lb + 1 - c2)/(double)(rb - lb + 1);
        ans += a[i].p;
    }
    printf("%.8f\n",ans*2000);
    return 0;
}