A~F 个人题解
A
#include <iostream>
using namespace std;
int main() {
int n,k;
cin>>n>>k;
if (k <= (n+9)/10)
cout<<"Gold Medal"<<'\n';
else if (k <= (n+9)/10*3)
cout<<"Silver Medal"<<'\n';
else if (k <= (n+9)/10*6)
cout<<"Bronze Medal"<<'\n';
else
cout<<"Da Tie"<<'\n';
return 0;
}
B
要么直接取最大的牌 要么弃掉所有牌获得点数为n的牌
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
while (t--) {
int n,x, mx = 0;
cin>>n;
for (int i=1; i<=n; i++)
cin>>x, mx = max(mx, x);
cout<<max(mx, n)<<'\n';
}
return 0;
}
C
要么1次 要么2次 因为总可以一次涂所有的0 一次涂所有的1
则当且仅当字符串本身就是回文串时涂1次 否则2次
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
while (t--) {
string s;
cin>>s;
string t(s.rbegin(), s.rend());
cout<<(t == s ? 1 : 2)<<'\n';
}
return 0;
}
D
即 从2n个数中取n个数 使得这n个数的按位与最大
对于从高到低的每个位 统计有多少个数在该位上为1 且在之前的计入ans的高位上也都为1
如果这样的数的个数不少于n个 则该位取1 否则取0
#include <iostream>
#include <bitset>
using namespace std;
long long a[400005];
int main() {
int t;
cin>>t;
while (t--) {
int n;
cin>>n;
for (int i=1; i<=n*2; i++)
cin>>a[i];
bitset<34> bs;
for (int j=33; j>=0; j--) {
int cnt = 0;
for (int i=1; i<=n*2; i++)
if (a[i]>>j&1 && (a[i]&bs.to_ullong()) == bs.to_ullong())
cnt++;
if (cnt >= n)
bs[j] = 1;
}
cout<<bs.to_ullong()<<'\n';
}
return 0;
}
E
考虑容斥原理 用总数减去非美丽的子序列个数
对于一个序列,如果它是非美丽的,则这个序列中必存在一个最小的数x,序列中所有数都是x的倍数
枚举每个数的倍数,统计
的倍数的个数
则以为最小值的子序列个数为
枚举倍数是一个调和级数 复杂度是
的
#include <iostream>
#include <cstring>
using namespace std;
const int M = 998244353;
int a[200005];
long long pow(long long a, int k) {
return k ? pow(a*a%M, k/2)*(k%2?a:1)%M : 1;
}
int main() {
int t;
cin>>t;
while (t--) {
int n,x;
cin>>n;
memset(a, 0, sizeof a);
for (int i=1; i<=n; i++)
cin>>x, a[x]++;
long long ans = 0;
for (int i=1; i<=n; i++) {
long long s = 0;
for (int j=i*2; j<=n; j+=i)
s += a[j];
ans += pow(2, s)*(pow(2, a[i])-1)%M;
}
cout<<((pow(2, n)-1-ans)%M+M)%M<<'\n';
}
return 0;
}
F
赛后补题
状压dp 需要预处理前缀和
第一次见这种前缀和 感觉很巧妙
#include <iostream>
#include <cstring>
using namespace std;
const int M = 1e9+7;
int dp[1<<20], s[1<<20];
int main() {
int t;
cin>>t;
while (t--) {
int n, a[20], b[20];
cin>>n;
string t;
for (int i=0; i<n; i++) {
cin>>t;
int ans = 0, mn = 1e9;
for (auto &ch: t)
ans += ch == '(' ? 1 : -1, mn = min(mn, ans);
a[i] = ans;
b[i] = mn;
}
for (int i=1; i<1<<n; i++)
s[i] = s[i^(i&-i)] + a[__builtin_ctz(i)];
if (s[(1<<n)-1] != 0) {
cout<<0<<'\n';
continue;
}
memset(dp, 0, sizeof dp);
dp[0] = 1;
for (int i=0; i<1<<n; i++)
for (int j=0; j<n; j++) {
if (i>>j&1 || s[i]+b[j] < 0)
continue;
dp[i|1<<j] += dp[i];
dp[i|1<<j] %= M;
}
cout<<dp[(1<<n)-1]<<'\n';
}
return 0;
}