Caddiプログラミングコンテスト2021(AtCoder初心者コンテスト193)-D-ポーカー-题解


一般的なアイデア

1から9までのK枚のカードがあり、それぞれが5枚のカードに分けられます。
スコアリングルールは次のとおりです。∑ i = 1 9i×10 ci \ displaystyle \ sum_(i = 1)^ 9 i \ times 10 ^(c_i)i = 19××1 0c,其中 C i C_i Cこの人は免許を持っていますかiiiのシート数。
各人が4枚のカードを配ったら、最初の人に勝つ確率を尋ねます。


問題解決のアイデア

③∑ i = 1 9i ×10 ci \ displaystyle \ sum_ {i = 1} ^ 9 i \ times 10 ^ {c_i}i = 19××1 0cあなたがすべてを理解していれば言うのは簡単です。
この文の意味は、4つの2がある場合、2 * 10000(4 0s)ポイントが付与されるということです。1 3、3 * 10(1 0)ポイントを取得します。5枚が0枚の場合、5 * 1(0 0)ポイントを獲得できます。

一人一人のカードの状況を列挙し、全体の状況に対する勝ちの状況の割合を計算することができます。
一人称の最後の写真は1、二人称の最後の写真は2、合計9件、
一人称の最後の写真は5、二人称の最後の写真は6、合計18ケース;
…… (純粋に架空の)
一人称1-9、二人称1-9、合計81回を列挙する必要があります。

2枚の山に3枚、1枚のカードが9枚残っている場合、1人目が2枚、2人目が1枚になるとすると、1人目は合計A 3 1 = 3 A ^ {1} _3になります。 = 3A31=3つのケースでは、2人目の人の合計はA 9 1 = 9 A ^ {1} _ 9 = 9です。A91=9ケース、合計3 ∗ 9 = 27 3 * 9 = 2739=2つの7の状況。
デッキに91が残っている場合、最初の人が1を取得し、2番目の人も1を取得することを考慮すると、合計A 9 2 = 72 A ^ {2} _9 = 72A92=7 2例でした。
いずれにせよ、全体の状況は次のとおりです。A残りのシート数2 A ^ {2} _ {残りのシート数}A以上残った2


ACコード

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;

ll getScore(ll s[]) //计算总得分
{
    
    
    ll ans=0;
    for(ll i=1;i<10;i++)
    {
    
    
        ans+=i*pow(10,s[i]);
    }
    return ans;
}
int main()
{
    
    
    ll k;
    cin >> k; 
    char s[10], t[10];
    cin >> s >> t;
    ll shengyu[10] = {
    
    0}; //shengyu[i]表示i还剩多少张
    for (ll i = 1; i < 10; i++)
        shengyu[i] = k; //没有发牌时1~9都各剩k张
    ll suma[10] = {
    
    0}; //s中有每种牌各多少
    ll sumb[10] = {
    
    0}; //t中有每种牌各多少
    for (ll i = 0; i < 4; i++) //已经发下来的前4张
    {
    
    
        shengyu[s[i] - '0']--; //第一个人起到了s[i],s[i]的剩余张数减1
        shengyu[t[i] - '0']--; //第一个人起到了t[i],t[i]的剩余张数减1
        suma[s[i]-'0']++;//第一个人起到了s[i],第一个人的s[i]的张数加1
        sumb[t[i]-'0']++;//第一个人起到了t[i],第一个人的t[i]的张数加1
    }
    ll canWin=0; //所有可以获胜的情况
    for (ll i = 1; i <= 9; i++) //第一个人起到了i
    {
    
    
        for (ll j = 1; j <= 9; j++) //第二个人起到了j
        {
    
    
            bool sfbx=false; //这种情况是否不行(当剩余牌没有i和j时,这种情况不行)
            if(shengyu[i]<=0)sfbx=true; //没i了
            if(shengyu[j]<=0)sfbx=true; //没j了
            if(i==j && shengyu[i]<=1)sfbx=true; //没有两张i
            suma[i]++; //第一个人起到了i
            sumb[j]++; //第二个人起到了j
            if(!sfbx) //不是不行
            {
    
    
                ll sa=getScore(suma); //第一个人的得分
                ll sb=getScore(sumb); //第二个人的得分
                if(sa>sb) //第一个人获胜
                {
    
    
                    if(i==j) //两人最后一张牌相同
                        canWin += shengyu[i] * (shengyu[i]-  1);
                    else
                        canWin += shengyu[i] * shengyu[j];
                }
            }
            suma[i]--; //这种情况考虑结束,放回最后一张牌
            sumb[j]--;
        }
    }
    ll shengyuAll = k*9-8; //所有剩余的牌
    ll canAll = shengyuAll*(shengyuAll-1); //所有可能的情况(对应A shengyuAll 2)
    double ans = 1. * canWin / canAll;
    printf("%.15lf\n", ans);
    return 0;
}

おすすめ

転載: blog.csdn.net/Tisfy/article/details/114196389