Codeforces 626 D. Jerry's Protest(概率DP)

codeforces每日一練。
題意:
有n張卡片,卡片上的數字就是分數,比如說甲乙兩人抽卡,三局兩勝,一局得分高的勝,求在甲贏了兩局的情況下乙贏了第三局且總分比甲高的概率。

思路:

  1. 數據1e3,很明顯的On^2算法,所以考慮暴力。
  2. 把分數數組排序,然後用cnt每輪可能出現的情況個數,cnt1統計分數差出現次數,cnt2統計甲前兩局領先乙的總分方案數。
  3. 很明顯,排序後的a[n]爲最大得分,所以可以遍歷1~a[n],兩層循環統計甲前兩局領先乙的總分方案數,cnt2[i+j]=cnt1[i]*cnt1[j] 。
  4. 最後也是兩層循環,枚舉分差,每對可能出現的分差對答案的貢獻爲:
    cnt1[i] * cnt2[j] / cnt / cnt / cnt 。 (除以每輪的方案數)

代碼如下:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}ll Inv(ll x,ll p){return qp(x,p-2,p);}
ll Cal(ll n,ll m,ll p){if (m>n) return 0;ll ans = 1;for(int i = 1; i <= m; ++i)
ans=ans*Inv(i,p)%p*(n-i+1)%p;return ans%p;}

const int manx=2e4+5;

ll a[manx],cnt1[manx],cnt2[manx];

int main(){
    ll n=read(),cnt=0;
    for(int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<i;j++)
            cnt1[a[i]-a[j]]++,++cnt;
    for(int i=1;i<=a[n];i++)
        for(int j=1;j<=a[n];j++)
            cnt2[i+j]+=cnt1[i]*cnt1[j];
    double ans=0;
    for(int i=1;i<=a[n];i++)
        for(int j=1;j<i;j++)
            ans+=cnt1[i]*cnt2[j]*1.0/cnt/cnt/cnt;
    printf("%.7f",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章