Educational Codeforces Round 181 (Rated for Div. 2) ABCD题解
A. Difficult Contest
题意:
重新规划s,使其没有FFT" 或 "NTT
思路:
倒着排即可
代码
void solve() {
string s;
cin >> s;
map<char, int> mp;
for (int i = 0; i < s.size (); ++i) {
mp[s[i]] ++;
}
for (int i = 25; i >= 0; --i) {
if (mp[(char)('A' + i)]) {
for (int j = 0; j < mp[char ('A' + i)]; ++j) cout << (char)('A' + i);
}
}
cout << "\n";
}
B. Left and Down
题意:
略
思路:
\(ans = [1, 2]\),分类讨论即可。
代码
void solve() {
ll a, b, k;
cin >> a >> b >> k;
ll q = __gcd (a, b);
if (k >= a / q && k >= b / q) {
cout << "1" << "\n";
}else{
cout << "2" << "\n";
}
}
C. Count Good Numbers
题意:
找出\([l,r]\)中不含2,3,5,7因子数字的个数。
思路:
容斥原理
\(|A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |B \cap C| - |C \cap A| + |A \cap B \cap C|\)
代码
ll cal (ll a) {
ll temp = 0;
temp += a / 2;
temp += a / 3;
temp += a / 5;
temp += a / 7;
temp -= a / 6;
temp -= a / 10;
temp -= a / 14;
temp -= a / 15;
temp -= a / 21;
temp -= a / 35;
temp += a / 30;
temp += a / 42;
temp += a / 105;
temp += a / 70;
temp -= a / 210;
return a - temp;
}
void solve() {
ll a, b;
cin >> a >> b;
cout << cal (b) - cal (a - 1) << "\n";
}
D. Segments Covering
题意:
有一条长度为 \(m\) 的线段,被划分成从 1 到 \(m\) 编号的 \(m\) 个单元格。给出 \(n\) 个区间,第 \(i\) 个区间用四个数 \((l_i, r_i, p_i, q_i)\) 描述:覆盖范围是闭区间 \([l_i, r_i]\)以概率 \(\frac{p_i}{q_i}\) 独立地出现(否则就不出现)。问:每个单元格都被恰好一条出现的区间覆盖 的总概率是多少?结果按最简分数 \(\frac{x}{y}\) 输出 \(x \cdot y^{-1} \mod 998244353\)。
思路:
考虑dp
状态设计
\[dp[r]=Pr(前 r 个格子都已合法覆盖的概率)
\]
转移方程
枚举每个右端点 \(r = 1..m\),再枚举所有以 \(r\) 结尾的区间 \((l, r)\):
- 左侧已合法的概率: \(\text{dp}[l-1]\)
- 区间自身出现的概率: \(p_i^*\)
- 区间段 \((l, r]\) 内其他右端点 \(\leq r\) 的区间全部不出现:\[\frac{\text{pref}[r]}{\text{pref}[l-1]} \]
- 上一步里把当前区间自己的 \(w_i\) 也乘进去了,需要除回去,并与第 2 步合并成\[\frac{p_i^*}{1 - p_i^*} \]
于是贡献为
\[\text{dp}[l-1] \times \frac{p_i^*}{1 - p_i^*} \times \frac{\text{pref}[r]}{\text{pref}[l-1]}
\]
把所有区间的贡献累加得到 \(\text{dp}[r]\)。
代码
#include<bits/stdc++.h>
#define ll long long
#define ce cerr
#define ull unsigned long long
#define lll __int128
using namespace std;
const int inf = 0x3f3f3f3f;
const ll iinf = 1e18;
const int mod = 998244353;
//cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
int t;
ll ksm (ll a, ll b) {
ll temp = 1;
while (b) {
if (b & 1) temp = temp * a % mod;
b >>= 1;
a = a * a % mod;
}
return temp;
}
struct node {
ll l, r, p;
};
bool cmp (node a, node b) {
return a.l < b.l;
}
void solve() {
ll n, m;
cin >> n >> m;
vector<ll> dp (m + 1, 0);
dp[0] = 1;
vector<ll> mul (m + 1);
vector<node> nd (n + 1);
for (int i = 0; i <= m; ++i) mul[i] = 1;
for (int i = 1; i <= n; ++i) {
ll l, r, p, q;
cin >> l >> r >> p >> q;
ll pp = ksm (q, mod - 2) * p % mod;
nd[i].l = l;
nd[i].r = r;
nd[i].p = pp;
ll temp = (1 - pp + mod) % mod;
mul[r] = mul[r] * temp % mod;
}
for (int i = 1; i <= m; ++i) {
mul[i] = mul[i - 1] * mul[i] % mod;
}
sort (nd.begin () + 1, nd.end (), cmp);
for (int i = 1; i <= n; ++i) {
ll temp = dp[nd[i].l - 1] * nd[i].p % mod * mul[nd[i].r] % mod * ksm (mul[nd[i].l - 1], mod - 2) % mod * ksm ((1 - nd[i].p + mod) % mod, mod - 2) % mod;
dp[nd[i].r] = (dp[nd[i].r] + temp) % mod;
}
cout << dp[m] << "\n";
}
int main() {
ios::sync_with_stdio (false);
cin.tie(NULL);
cout.tie(NULL);
t = 1;
// cin >> t;
while (t --) {
solve();
}
return 0;
}