Problem
某种麻将有34种牌型,每种牌型都有四张。现在手上有13张牌,每种类型的牌不超过2张。
每次可以从牌堆摸一张牌,且必须弃一张牌(不放会牌堆)。当手上14张牌是7种不同的对子时,立刻获胜。
问:在采用最优策略的情况下,获胜的期望摸牌轮数。
Solution
最优策略:若摸到的牌可以凑成对子,则随机丢弃一张单牌;否则丢弃摸到的牌。
证明:
每次摸完一张牌后,牌堆中该种牌型最多剩余三张。
牌堆中该种牌剩余的数量可能是0、1、2、3,而牌堆中手中每种单牌剩余的数量都是3张。
刚摸到的牌未来成对的概率只会更差,所以丢弃刚摸到的牌更优。
Code
const ll mod = 1000000007;
using namespace std;
const int N = 4e5 + 5, M = 1e6 + 7;
ll f[20][200];
ll ksm(ll a, ll b)
{
ll ans = 1;
for (; b; b >>= 1)
{
if (b & 1) ans = a * ans % mod;
a = a * a % mod;
}
return ans;
}
int main()
{
IOS;
for (int i = 1; i <= 13; i += 2)
for (int j = 1; j <= 123; j++)
if (i * 3 <= j)//采取最优策略,牌堆中最少剩余 i * 3 张牌
{
ll inv = ksm(j, mod - 2);
f[i][j] = 1 + 3 * i * inv % mod * f[max(0, i - 2)][j - 1] % mod +
(j - 3 * i) * inv % mod * f[i][j - 1] % mod;
f[i][j] %= mod;
}
int T, cas = 0; cin >> T;
while (T--)
{
map<string, int>mp;
string s; cin >> s;
for (int i = 0; i < 26; i += 2)
mp[s.substr(i, 2)]++;
int c = 0;
for (auto it : mp)
if (it.sd == 1) c++;
cout << "Case #" << ++cas << ": ";
cout << f[c][123] << endl;
}
return 0;
}