NC205448. 欢乐斗地主
描述
单走一个6,▇ ▇,直接把K走了。
走他一张2顶他。阿姨快点,阿姨,阿姨你K都不要吗?阿姨你快点啊!阿姨别磨磨蹭蹭的。
阿姨正在打斗地主。她手里有张牌,这张牌只由和构成。
上家出了一张K,现在轮到她出牌。接下来阿姨会尝试找到一张打出去。
阿姨的出牌过程会进行秒,第秒会依次进行以下操作:
在第秒结束后,如果阿姨没有找到,她会选择要不起并结束操作。
求阿姨期望被倒多少杯卡布奇诺。答案对998244353取模。
输入描述
第一行一个整数。
接下来一个长为的字符串,表示第张牌上的数字。
输出描述
输出一个数,表示答案在模998244353意义下的值。
示例1
输入:
2 32
输出:
2
说明:
第一秒,阿姨会被倒一杯卡布奇诺,之后她会检查第一张牌。之后无论地主替换哪张牌,阿姨都会在第二秒被倒一杯卡布奇诺。C++14(g++5.4) 解法, 执行用时: 43ms, 内存消耗: 13164K, 提交时间: 2020-06-19 19:50:08
#include <bits/stdc++.h> const int moder = 998244353; const int N = 1000010; char s[N]; int fac[N], inv[N], invf[N]; void add(int &a, int b){ a += b; a -= a >= moder ? moder : 0; } int main(){ int n; scanf("%d%s", &n, s); fac[0] = invf[0] = 1; for (int i = 1; i < N; ++ i){ fac[i] = 1ll * fac[i - 1] * i % moder; inv[i] = i == 1 ? 1 : moder - 1ll * (moder / i) * inv[moder % i] % moder; invf[i] = 1ll * invf[i - 1] * inv[i] % moder; } if (s[0] == '2'){ puts("1"); return 0; } int ans = 0, prod = 1, prob = 1; int cnt = 0; for (int i = 0; i < n; ++ i){ add(ans, prob); if (s[i] == '2'){ prod = 1ll * prod * (i - cnt) % moder; ++ cnt; prob = 1ll * prod * fac[n - cnt] % moder * invf[n] % moder; } } printf("%d\n", ans); }
C++11(clang++ 3.9) 解法, 执行用时: 33ms, 内存消耗: 10284K, 提交时间: 2020-06-24 08:38:00
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+5,mod=998244353; int n; ll f[N]; char s[N]; ll qpow(ll a,ll n) { ll ans=1; for(;n;n>>=1,a=a*a%mod) if(n&1) ans=ans*a%mod; return ans; } int main() { f[0]=1;for(int i=1;i<N;i++) f[i]=f[i-1]*i%mod; scanf("%d",&n); scanf("%s",s+1); int k=0; ll p=1,ans=0; for(int i=1;i<=n;i++) { ans=(ans+p*f[n-k])%mod; if(s[i]=='2') { p=p*(i-1-k)%mod; k++; } } printf("%lld\n",ans*qpow(f[n],mod-2)%mod); }