Caddi Programming Contest 2021(AtCoder Beginner Contest 193)-D - Poker-题解


General idea

There are K cards from 1 to 9, and each is divided into 5 cards.
The scoring rule is ∑ i = 1 9 i × 1 0 ci \displaystyle \sum_(i=1)^9 i \times 10^(c_i)i=19i×10ci, Among them C i C_iCiIs this person has a license iiThe number of sheets of i .
When each person has dealt 4 cards, ask the first person the probability of winning.


Problem-solving ideas

∑ i = 1 9 i × 1 0 c i \displaystyle \sum_{i=1}^9 i \times 10^{c_i} i=19i×10ciIt's easy to say if you understand everything.
The meaning of this sentence is that if there are 4 2s, then 2 * 10000 (4 0s) points will be awarded. 1 3, get 3 * 10 (1 0) points. If you have 0 sheets of 5, you will get 5 * 1 (0 0) points.

We can enumerate the situation of each person's cards, and calculate the proportion of the winning situation to the total situation.
The last picture of the first person is 1, the last picture of the second person is 2, a total of 9 cases; the
last picture of the first person is 5, the last picture of the second person is 6, a total of 18 cases;
…… (Purely fictitious)
Need to enumerate the first person 1-9, the second person 1-9, a total of 81 times.

If there are 3 cards left in the pile of 2, and 9 cards of 1, considering that the first person gets 2 and the second person gets 1, the first person has a total of A 3 1 = 3 A^{1}_3=3A31=In 3 cases, the second person has a total ofA 9 1 = 9 A^{1}_9=9A91=9 cases, a total of3 ∗ 9 = 27 3*9=2739=2 7 situations.
If there are 9 1s left in the deck, considering that the first person gets 1 and the second person gets 1 too, a total ofA 9 2 = 72 A^{2}_9=72A92=7 2 cases.
In any case, the total situation isA remaining number of sheets 2 A^{2}_{remaining number of sheets}ALeft more than Zhang number2


AC code

#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;
}

Guess you like

Origin blog.csdn.net/Tisfy/article/details/114196389