牛客周赛 Round 112 题解,C++ version。
A ICPC Regionals
用 判断一下即可,
(整数意义下)。
void solve() {
int n, k;
cin >> n >> k;
if (k <= (n + 9) / 10) cout << "Gold Medal" << "\n";
else if (k <= 3 * (n + 9) / 10) cout << "Silver Medal" << "\n";
else if (k <= 6 * (n + 9) / 10) cout << "Bronze Medal" << "\n";
else cout << "Da Tie" << "\n";
}
B Card Game
要么取点数最大的那张,要么把所有牌丢掉取 。
void solve() {
int n, mx = 0;
cin >> n;
for (int i = 1; i <= n; ++i) {
int x;
cin >> x;
mx = max(mx, x);
}
cout << max(mx, n) << "\n";
}
C Palindrome Coloring
分别取出所有 和所有
即可处理所有情况,特判一下回文即可。
void solve() {
string s;
cin >> s;
char tar = s[0];
bool f = true;
for (int i = 0; i <= s.size() / 2; ++i) {
if (s[i] != s[s.size() - i - 1]) {
f = false;
break;
}
}
if (f) cout << 1 << "\n";
else cout << 2 << "\n";
}
D Digital Pairing
从最大到最小逐一贪心,如果不影响先前位的情况下,这一位为 的数量大于等于
,这一位就可以置
。
void solve() {
int n;
cin >> n;
vector<int> a(2 * n + 1);
for (int i = 1; i <= 2 * n; ++i) cin >> a[i];
int ans = 0;
for (int mask = 31; mask >= 0; --mask) {
int cnt = 0, cand = ans | (1 << mask);
for (int i = 1; i <= 2 * n; ++i) {
if ((cand & a[i]) == cand) cnt++;
}
if (cnt >= n) ans = cand;
}
cout << ans << "\n";
}
一个更容易理解的写法
void solve() {
int n;
cin >> n;
vector<int> a(2 * n + 1);
for (int i = 1; i <= 2 * n; ++i) cin >> a[i];
int ans = 0;
for (int mask = 31; mask >= 0; --mask) {
vector<int> b = a;
a.clear();
ll cand = ans | (1 << mask);
for (auto v : b) {
if ((cand & v) == cand) a.pb(v);
}
if (a.size() >= n) ans = cand;
else a = b;
}
cout << ans << "\n";
}
E Beautiful Sequence
一道正难则反的题目。 显然答案为 ,我们只需要枚举
,它和它的所有倍数即可构成所有非美丽序列。
void solve() {
int n;
cin >> n;
vector<int> cnt(maxn + 10);
for (int i = 1; i <= n; ++i) {
int x;
cin >> x;
cnt[x]++;
}
Z ans = power(Z(2), n) - 1;
for (int i = 1; i <= maxn; ++i) {
int len = 0, st;
if (cnt[i]) {
len += cnt[i];
st = cnt[i];
for (int j = i + i; j <= maxn; j += i) {
len += cnt[j];
}
for (int j = 1; j <= st; ++j) {
ans -= power(Z(2), len - j);
}
}
}
cout << ans << "\n";
}
当然也可以正做。
对于每个 ,记
为“由数组中所有能被
整除的元素构成的、且
恰好为
的非空子序列数”。
我们可以用常见的“枚举倍数,从大到小消去”的方法得到所有的 。
其中 是数组中能被
整除的元素个数,
是这些元素的所有非空子序列数。
但我们真正需要的是不包含值为 的那些子序列(即子序列中不出现
),设为
,在所有只选取“能被
整除”的子序列中,恰好包含至少一个等于
的子序列数为
其中 是数组中等于
的数字个数;因为选至少一个等于
的数字方案有
中,其他位置任意选或不选,因此
最终答案就是对所有 (
),将
累加并对
取模。
void solve() {
int n;
cin >> n;
vector<int> cnt(maxn + 10);
for (int i = 1; i <= n; ++i) {
int x;
cin >> x;
cnt[x]++;
}
vector<int> m(n + 1, 0);
for (int d = 1; d <= n; ++d) {
for (int j = d; j <= n; j += d) m[d] += cnt[j];
}
vector<Z> p2(n + 1, 1);
for (int i = 1; i <= n; ++i) p2[i] = p2[i - 1] + p2[i - 1];
vector<Z> G(n + 1, 0);
for (int d = 1; d <= n; ++d) {
if (m[d] == 0) G[d] = 0;
else G[d] = p2[m[d]] - 1;
}
vector<Z> f(n + 1, 0);
for (int d = n; d >= 1; --d) {
Z val = G[d];
for (int dk = d * 2; dk <= n; dk += d) {
val -= f[dk];
}
f[d] = val;
}
vector<Z> S(n + 1, 0);
for (int d = 1; d <= n; ++d) {
if (m[d] == 0) {
S[d] = 0;
continue;
}
S[d] = p2[m[d]] - p2[m[d] - cnt[d]];
}
Z ans = 0;
for (int d = 1; d <= n; ++d) {
Z fp = f[d] - S[d];
ans += fp;
}
cout << ans << "\n";
}
F Bracket Counting
如果记 ‘(' 为 ,‘)' 为
,如果一个括号序列是合法的,那么对于每一位,都有前缀和
。
记这个括号序列等价表示的最小值为 ,那么如果
那么
最终答案即为 ,注意需要特判不合法的情况。
void solve() {
int n;
cin >> n;
vector<int> a(n), b(n);
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
int mn = 0;
for (auto v : s) {
if (v == '(') a[i]++;
else a[i]--;
mn = min(mn, a[i]);
}
b[i] = mn;
}
int m = 1 << n;
vector<int> pre(m);
for (int i = 1; i < m; ++i) {
int prev = __builtin_ctz(i);
pre[i] = pre[i ^ (1 << prev)] + a[prev];
}
if (pre[m - 1] != 0) {
cout << 0 << "\n";
return;
}
vector<Z> dp(m);
dp[0] = 1;
for (int i = 0; i < m; ++i) {
if (dp[i] == 0) continue;
int S = pre[i];
for (int j = 0; j < n; ++j) {
if ((i >> j) & 1) continue;
if (S + b[j] >= 0) {
int nxt = i | (1 << j);
dp[nxt] += dp[i];
}
}
}
cout << dp[m - 1] << "\n";
}
头文件
//Another
#include<bits/stdc++.h>
#include<bits/extc++.h>
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef tuple<ll, ll, ll> TLLL;
typedef __gnu_pbds::tree<PLL, __gnu_pbds::null_type, less<PLL>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> Tree;
// typedef __gnu_pbds::tree<ll, __gnu_pbds::null_type, less<ll>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> Tree;
constexpr int inf = (ll)1e9 + 7;
constexpr ll INF = (ll)2e18 + 9;
// constexpr ll INF = (ll)4e18;
// constexpr ll MOD = 1e9 + 7;
constexpr ll MOD = 998244353;
constexpr ld PI = acos(-1.0);
constexpr ld eps = 1e-10;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ull randint(ull l, ull r) {uniform_int_distribution<unsigned long long> dist(l, r); return dist(rng);}
void init() {
}
void solve() {
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
init();
int t = 1;
cin >> t;
for (int _ = 1; _ <= t; ++_) {
solve();
}
return 0;
}
自动取模
template<class T>
constexpr T power(T a, ll b) {
T res = 1;
while (b) {
if (b & 1) res *= a;
b >>= 1;
a *= a;
}
return res;
}
template<int P>
struct MInt {
int x;
constexpr MInt(): x() {}
constexpr MInt(ll x) : x{norm(x % getMod())} {}
static int Mod;
constexpr static int getMod() {
if (P > 0) {
return P;
} else {
return Mod;
}
}
constexpr static void setMod(int Mod_) {
Mod = Mod_;
}
constexpr int norm(int x) const {
if (x < 0) {
x += getMod();
}
if (x >= getMod()) {
x -= getMod();
}
return x;
}
constexpr int val() const {
return x;
}
explicit constexpr operator int() const {
return x;
}
constexpr MInt operator-() const {
MInt res;
res.x = norm(getMod() - x);
return res;
}
constexpr MInt inv() const {
assert(x != 0);
return power(*this, getMod() - 2);
}
constexpr MInt &operator*=(MInt rhs) & {
x = 1LL * x * rhs.x % getMod();
return *this;
}
constexpr MInt &operator+=(MInt rhs) & {
x = norm(x + rhs.x);
return *this;
}
constexpr MInt &operator-=(MInt rhs) & {
x = norm(x - rhs.x);
return *this;
}
constexpr MInt &operator/=(MInt rhs) & {
return *this *= rhs.inv();
}
friend constexpr MInt operator*(MInt lhs, MInt rhs) {
MInt res = lhs;
res *= rhs;
return res;
}
friend constexpr MInt operator+(MInt lhs, MInt rhs) {
MInt res = lhs;
res += rhs;
return res;
}
friend constexpr MInt operator-(MInt lhs, MInt rhs) {
MInt res = lhs;
res -= rhs;
return res;
}
friend constexpr MInt operator/(MInt lhs, MInt rhs) {
MInt res = lhs;
res /= rhs;
return res;
}
friend constexpr istream &operator>>(istream &is, MInt &a) {
ll v;
is >> v;
a = MInt(v);
return is;
}
friend constexpr ostream &operator<<(ostream &os, const MInt &a) {
return os << a.val();
}
friend constexpr bool operator==(MInt lhs, MInt rhs) {
return lhs.val() == rhs.val();
}
friend constexpr bool operator!=(MInt lhs, MInt rhs) {
return lhs.val() != rhs.val();
}
};
template<>
int MInt<0>::Mod = 998244353;
using Z = MInt<MOD>;