2022牛客暑期多校1_I-Chiitoitsu_概率DP
I-Chiitoitsu_概率DP
题目大意:
初始手牌有 13 张麻将牌,相同牌至多出现 2 张
每轮可以从牌堆摸牌,若达成七对子则自摸胡牌
若不然则选择手牌中某张牌并丢弃之
给定初始手牌,求最优策略下达成七对子的期望轮数
多组数据,数据组数不超过 1e5
思路和代码:

搞懂这个dp推荐读者把dp数组打出来看一下
int n , m , k ;
ll dp[20][200] ;
inline ll quick_pow(ll a, ll k, ll p) {
ll res = 1;//快速幂
a %= p;
while (k) {
if (k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}
inline ll inv(ll x,ll p){//逆元
return quick_pow(x,p-2,p);
}
void solve(){
string s ; cin >> s ;
n = s.size() ;
ll cnt = 0 ;
map<string , int> mp ;
for(int i = 0 ; i < n ; i += 2)
mp[s.substr(i , 2)] ++ ;
for(auto x : mp){
cnt += x.se == 1 ;
}
// cout << cnt << " " << m << "\n" ;
cout << dp[cnt][m] << "\n" ;
}//code_by_tyrii
int main(){
// freopen("in.in" , "r" , stdin) ;
ios::sync_with_stdio(false) ;
cin.tie(0) ; cout.tie(0) ;
m = 9 * 4 * 3 + 7 * 4 - 13 ;//牌堆
rep(j , 3 , m)
dp[1][j] = (((j - 3) * (inv(j , mod)) % mod) * dp[1][j - 1] % mod + 1ll) % mod;
for(int i = 3 ; i <= 13 ; i += 2)
rep(j , 3 , m){
ll tmp1 = ((3 * i % mod) * inv(j , mod) % mod) * dp[i - 2][j - 1] % mod ;
ll tmp2 = (((j - 3 * i + mod) % mod) * inv(j , mod) % mod) * dp[i][j - 1] % mod ;
dp[i][j] = ((tmp1 + tmp2) % mod + 1LL) % mod ;
}
ll T ; cin >> T ;
rep(i , 1 , T){
cout << "Case #" << i << ": " ;
solve() ;
}
}

浙公网安备 33010602011771号