题解 | #Course#
Chiitoitsu
https://ac.nowcoder.com/acm/contest/33186/I
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 different types of tiles, and there are 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 tiles, which means that he will get tiles from the stockpile. These 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 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 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 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
It can be shown that the answer can be represented as a fraction , where and are both positive integers and coprime. If there exists a non-negative integer less than satisfying =$$p, we call the integer the result of modulo
输入描述
Each test consists of multiple test cases.
The first line contains a single integer — the number of test cases.
Each line of the following lines describes a test case and contains a string of 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 -th test case, print a line containing "Case # : " where is the number of the test case starting from and is the answer to the test case.
输入样例:
2
1m9m1p9p1s9s1z2z3z4z5z6z7z
1m1m4m5m1p4m2m2m2p2p2s2s2z
输出样例:
Case #1: 927105416
Case #2: 100000041
题意
给定 张麻将,开局给定一个长度为 的字符串描述初始的 张手牌(保证初始手牌相同花色的麻将不会超过两张),每一轮可以从牌库中抽取一张麻将,并选择一张麻将打出(打出的麻将不会回到牌库)当摸到一张麻将加上手中的 张麻将构成 个对子的时候胜利 求最优策略下胜利的期望轮数对 取模
思路
首先是摸牌打牌策略,最优策略是摸到一张手牌若是自己的手牌中已经存在的单牌那么就选择一张别的单牌打出,此时手牌中单牌的数量减 ,否则就将摸到的牌打出。拆已经成对的牌显然是错误的,若是换张首先不会让手牌情况更优,反之若是换张可能会使情况更劣,例如将摸到的牌放入手牌并选择了一张单牌打出,而在下一轮摸到了上回合打出的那张单牌,这样的策略可能会使牌没法胡,因为能胡的牌被打出如此往复可能牌库中不存在当前单牌的花色。而若是抓到有的单牌放入没有的就弃牌可以保证最终是可以胡的。 对于手牌中不同的花色对期望是没有影响的,影响的只是初始手牌中单牌的数量,故只需处理出初始手牌中单牌的数量即可
对于 张初始手牌且相同花色至多有 张的情况下单牌数量只有 , , , , , , ,张的情况。这样我们就可以构建概率 的转移方程了
定义 为当前手牌中单牌的数量 为牌库中剩余的牌数
对于手中单牌数量为 的情况下且牌库就剩下 张牌及以下的情况下必定都是手中单牌所对应的花色故此时只需要再摸一张牌即操作一轮则必定胡 故
对于手中单牌数量为 的情况下 有 的概率可以直接胡牌不需要花费轮数 有 的概率可以花费 的轮数转移到
对于手中单牌数量为 的情况下 有 的概率可以花费 的轮数转移到 有 的概率可以花费 的轮数转移到
由于结果要 故对分母处理一下逆元即可
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;
}