I - Chiitoitsu

题目背景

Serval is learning Japanese Mahjong recently in order to play Mahjong Soul with his friends, HomuraCat, RanshiinSaikou, and Mocha.

Serval learned that in Japanese Mahjong, there are 3434 different types of tiles, and there are 44 tiles of each type. According to the suits and the tile types, the tiles can be divided into four groups. Three of them form the numbered suits, each with sequences from one to nine. They are the manzu, the pinzu, and the souzu. The other group is the jihai, which can be further divided into the kazehai and the sangenpai.

Serval uses two characters to describe a tile. The former is a number and the latter is one of 'm', 'p', 's' and 'z'. Specifically, the manzu, the pinzu and the souzu with the number kk are described as 'km', 'kp' and 'ks', respectively. For example, San man (the manzu tile with the number 3) is described as '3m', Rou pin (the pinzu tile with the number 6) is discribed as '6p', Kyuu sou (the souzu tile with the number 9) is discribed as '9s'. As for jihai, Ton, Nan, Shaa, Pei, Haku, Hatsu, Chun are described as '1z' to '7z', respectively. All types of tiles are listed below. 麻将类型实例

You may know that in Japanese Mahjong, winning a hand requires at least one yaku, where hand denotes the tiles a player holds. There are a large number of yaku types, and among them, Serval loves chiitoitsu most. Chiitoitsu is the hand that consists of seven distinct pairs. In other words, chiitoitsu consists of seven distinct types of tiles and two tiles of each type. In this problem, there is no need for you to learn what yaku exactly is. You only need to focus on chiitoitsu.

Serval loves chiitoitsu so much that he wants to practice winning hands with chiitoitsu. Note that the rules that Serval practices seeking chiitoitsu are different from those of Japanese Mahjong. At first, all the tiles are shuffled and placed face-down on the board as the stockpile. Then the only player, Serval, is dealt 1313 tiles, which means that he will get 1313 tiles from the stockpile. These 1313 tiles are called the start hand. In each turn, Serval can draw and discard in the following order:

  • Draw a tile from the stockpile.

    Serval gets a random tile from the stockpile. After that, he will hold 1414 tiles.

  • Tsumo if the hand reaches chiitoitsu.

    Serval declares a win immediately if his hand reaches chiitoitsu, and the game is over at the same time.

  • Discard a tile from the hand.

    Serval chooses a tile and removes it from his hand. After that, he will hold 1313 tiles. The discarded tile will be placed face-up on the board, which means it will not return to the stockpile.

Now Serval gets his start hand, and he wonders the expected number of turns to reach chiitoitsu if he carries out the optimal strategy. Surprisingly, Serval finds that there are no more than two tiles of the same type in his start hand. Serval simply concatenates the notation of each tile in the start hand, forming a string of 2626 characters to describe the start hand. However, Serval cannot find out the answer, so he tells you his start hand and asks you to help him. You only need to tell him the answer modulo 109+710^9+7

It can be shown that the answer can be represented as a fraction p/qp/q, where pp and qq are both positive integers and coprime. If there exists a non-negative integer rr less than 109+710^9+7 satisfying qrq \cdot r mod(109+7)mod (10^9+7) =$$p, we call the integer rr the result of p/qp/q modulo 109+710^9+7

输入描述

Each test consists of multiple test cases.

The first line contains a single integer TT (1T105)(1 \leq T \leq 10^5 ) — the number of test cases.

Each line of the following TT lines describes a test case and contains a string of 2626 characters — the start hand.

It is guaranteed that there are no more than two tiles of the same type in the start hand.

输出描述

For the ii-th test case, print a line containing "Case # ii : xx" where ii is the number of the test case starting from 11 and xx is the answer to the test case.

输入样例:

2
1m9m1p9p1s9s1z2z3z4z5z6z7z
1m1m4m5m1p4m2m2m2p2p2s2s2z


输出样例:

Case #1: 927105416
Case #2: 100000041

题意

给定 136136 张麻将,开局给定一个长度为 2626 的字符串描述初始的 1313 张手牌(保证初始手牌相同花色的麻将不会超过两张),每一轮可以从牌库中抽取一张麻将,并选择一张麻将打出(打出的麻将不会回到牌库)当摸到一张麻将加上手中的 1313 张麻将构成 77 个对子的时候胜利 求最优策略下胜利的期望轮数对109+710^9+7 取模

思路

首先是摸牌打牌策略,最优策略是摸到一张手牌若是自己的手牌中已经存在的单牌那么就选择一张别的单牌打出,此时手牌中单牌的数量减 22 ,否则就将摸到的牌打出。拆已经成对的牌显然是错误的,若是换张首先不会让手牌情况更优,反之若是换张可能会使情况更劣,例如将摸到的牌放入手牌并选择了一张单牌打出,而在下一轮摸到了上回合打出的那张单牌,这样的策略可能会使牌没法胡,因为能胡的牌被打出如此往复可能牌库中不存在当前单牌的花色。而若是抓到有的单牌放入没有的就弃牌可以保证最终是可以胡的。 对于手牌中不同的花色对期望是没有影响的,影响的只是初始手牌中单牌的数量,故只需处理出初始手牌中单牌的数量即可

对于 1313 张初始手牌且相同花色至多有 22 张的情况下单牌数量只有 113355779911111313 ,张的情况。这样我们就可以构建概率 dpdp 的转移方程了

定义 dp[d][p]dp[d][p] dd 为当前手牌中单牌的数量 pp 为牌库中剩余的牌数

对于手中单牌数量为 11 的情况下且牌库就剩下 33 张牌及以下的情况下必定都是手中单牌所对应的花色故此时只需要再摸一张牌即操作一轮则必定胡 故 dp[1][1]=dp[1][2]=dp[1][3]=1dp[1][1]=dp[1][2]=dp[1][3]=1

对于手中单牌数量为 11 的情况下 有 3/p3/p 的概率可以直接胡牌不需要花费轮数 有 (p3)/p(p-3)/p 的概率可以花费 11 的轮数转移到 dp[1]p1]dp[1]p-1]

对于手中单牌数量为 3,5,7,9,11,133,5,7,9,11,13 的情况下 有 3/p3/p 的概率可以花费 11 的轮数转移到 dp[d2][p1]dp[d-2][p-1](p3)/p(p-3)/p 的概率可以花费 11 的轮数转移到 dp[d][p1]dp[d][p-1]

由于结果要 modmod 109+710^9+7 故对分母处理一下逆元即可

Code

#include<bits/stdc++.h>
using namespace std;
#define __T int csT;scanf("%d",&csT);while(csT--)
#define endl '\n'
const int mod=1e9+7;
const double PI= acos(-1);
const double eps=1e-6;
const int N=2e5+7;

string s;
int qpow(long long a,long long x)
{
    long long ans=1;
    while(x>0)
    {
        if(x%2==1)
        {
            ans=(ans*a)%mod;
        }
        x>>=1;
        a=(a*a)%mod;
    }
    return ans;
}
long long inv(int a)
{
    return qpow(a,mod-2)%mod;
}
int dp[23][203];
unordered_map<string,int> mp;
int d=13;
int main()
{
    for(int i=0;i<=136-13;++i)
    {
        dp[0][i]=0;
    }
    dp[1][1]=dp[1][2]=dp[1][3]=1;
    for(int i=4;i<=136-13;++i)
    {
        dp[1][i]=((i-3)*inv(i)%mod*dp[1][i-1]%mod+1)%mod;
    }
    for(int i=3;i<=13;i+=2)
    {
        for(int j=3*i;j<=136-13;++j)
        {
            dp[i][j]=((j-3*i)*inv(j)%mod*dp[i][j-1]%mod+(3*i)*inv(j)%mod*dp[i-2][j-1]%mod+1)%mod;
        }
    }
    int cs=0;
    __T
    {
        cin>>s;
        mp.clear();
        d=13;
        for(int i=0;i<26;i+=2)
        {
            if(mp[s.substr(i,2)]==0)
            {
                mp[s.substr(i,2)]=1;
            }
            else if(mp[s.substr(i,2)]==1)
            {
                mp[s.substr(i,2)]=2;
                d-=2;
            }
        }
        printf("Case #%d: %d\n",++cs,dp[d][136-13]);
    }
    return 0;
}