“蔚来杯“2022牛客暑期多校训练营1 Chiitoitsu

Chiitoitsu

题目解析

        ~~~~~~~        题目本身就是搓麻将吗,首先要先思考题目中得最优策略是一种什么样的策略,首先题目已经告诉我们了初始手牌每一种牌数量最多是2,也就是不存在要丢弃多余的多张牌的情况,这是个很重要的性质,首先如果摸到的牌在手牌中已经凑到的2个,很显然要将摸到的给丢到,手牌不变,如果抽到的是已有的单牌,很显然配对然后随便丢一张单牌,如果拿到的是手牌中不存在的牌那么也将这张牌给丢掉,其实也就是只有抽到的牌能和手中的单牌配对时才拿,其他情况都丢弃,为什么不将手中的单牌替换呢?
        ~~~~~~~        我们思考我们要以最大的概率抽取我们手中拥有的单牌以便尽快的抽到,在牌堆数量一定的情况下,那么这种牌数量越多越好,显然要尽量使牌堆中这种牌的数量为3张,那么初始情况下,所有的已拥有的单牌在牌堆的数量显然都是最大的,如果将某一个单牌替换了,概率不会更优,所以不替换,这样如果不抽到就不换,如果抽到就直接配对,这样能使初始手牌中单牌抽到的概率始终使最大的。
        ~~~~~~~        此题一看就可以用期望dp来做,那么思考状态表示,显然在一种状态里将所有牌的状态都记录下来是不可能的,其实根据我们的策略就可以知道我们关注的只是我们手中的单牌以及此时的牌堆,其他东西都是无用的,并且在此题中很显然能看出来每一种牌本质是一样的,所以状态只需要记录2维,分别牌堆的数量和单牌的个数。
在这里插入图片描述
当单牌个数只有一个时,如果没抽到单牌,概率时(i-3)/i,状态变成dp[i-1][1];如果抽到了,那么完结了,那么此时的期望局数是0,不需要算,最后要加上当前局,也就是加1
在这里插入图片描述
多单牌时如果i==j*3,其实就是牌堆中只剩下手中拥有的单牌,那么必中,注意,在最优策略下,任一单牌在牌堆中的数量始终是3

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=200;
ll dp[N][20];
ll qmi(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1)res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res%mod;
}
int main()
{
    dp[3][1]=1;
    for(int i=4;i<=34*4-13;i++)
        dp[i][1]=(1+dp[i-1][1]*(i-3)%mod*qmi(i,mod-2)%mod)%mod;
    for(int j=3;j<=13;j+=2)
        for(int i=j*3;i<=34*4-13;i++)
        {
            if(i==3*j)dp[i][j]=(1+dp[i-1][j-2])%mod;
           else dp[i][j]=(1+(dp[i-1][j]*(i-j*3)%mod*qmi(i,mod-2)%mod+dp[i-1][j-2]*(3*j)%mod*qmi(i,mod-2)%mod)%mod);
        }
    int T;
    cin>>T;
    //T=1;
    for(int t=1;t<=T;t++)
    {
        string s;
        cin>>s;
        s=" "+s;
        int temp=13;
        for(int i=1;i<26;i+=2)
        {
            string str=s.substr(i,2);
            string ss;
            for(int j=i+2;j<26;j+=2)
            {
                ss=s.substr(j,2);
                if(str==ss)
                {
                    temp-=2;
                    break;
                }
            }
        }
        printf("Case #%d: %lld\n",t,dp[34*4-13][temp]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值