# AtCoder Beginner Contest 347 (A~E)
这场 C > E > D 不好评价...(D E 赛后一发过,被 C 卡死了)
A
模拟即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+5;
ll n, k, a[N];
int main(){
ios::sync_with_stdio(false);
cin >> n >> k;
for(int i = 1; i <= n; i ++){
cin >> a[i];
if(a[i] % k == 0) cout << a[i] / k << " ";
}
return 0;
}
B
也是直接暴力模拟即可,用 substr 会方便很多。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+5;
ll ans;
string s;
int main(){
ios::sync_with_stdio(false);
map<string, ll> mp;
cin >> s;
ll n = s.size();
for(int i = 1; i <= n; i ++){
for(int j = 0; j <= n - i; j ++){
string p = s.substr(j, i);
if(!mp[p]) ans ++;
mp[p] = 1;
}
}
cout << ans << endl;
return 0;
}
C
思维难度较大,赛时一直被卡一个点,很烦。
一开始的想法是找出取模后的最大值和最小值只差然后判断小于 a 即可。
如图:
只要 max - min 小于 a 就可以满足,这样做会 wa 1个点。
比如
2 2 1
1 3
应该输出 Yes,但是以上判断会输出 No。
正解:
对取模后的 D 数组排序,若两两之间能塞下一个 b 说明可以通过平移取模使得所有的点都落在小于 a 的范围内再加上之前的判断就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 2e5 + 5;
ll n, a, b, d[MAXN];
int main(){
cin >> n >> a >> b;
for(int i = 0; i < n; i ++){
cin >> d[i];
d[i] = (d[i] - 1) % (a + b);
}
sort(d, d + n);
for(int i = 1; i < n; i ++){
if(d[i] - d[i - 1] >= b){
cout << "Yes" << endl;
return 0;
}
}
if(d[n - 1] - d[0] < a) cout << "Yes" << endl;
else cout << "No" << endl;
return 0;
}
D
将 c 二进制分解后让 a 和 b 剩余没确定的数尽量相等,如果剩余数不能相等就 -1
再判断 a 和 b 是否大于 \(2^{60}\) 就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll MAXN = 2e5+5;
const ll MX = 1<<60;
ll a, b, c;
ll f[70], f1[70], f2[70];
ll fastPow(ll a, ll b){
ll res = 1;
while(b){
if(b & 1) res *= a;
a *= a;
b >>= 1;
}
return res;
}
int main(){
ios::sync_with_stdio(false);
cin >> a >> b >> c;
ll cnt = 0, ct = 0, c1 = 0, c2 = 0;
while(c){
if(c & 1) f[cnt] = 1;
cnt ++;
c /= 2;
}
for(int i = 0; i <= 60; i ++){
if(f[i]){
if((a - c1) >= (b - c2)){
f1[i] = 1;
c1 ++;
}
else{
f2[i] = 1;
c2 ++;
}
}
}
if((a - c1) != (b - c2)){
cout << "-1" << endl;
return 0;
}
else{
ll tt = (a - c1);
for(int i = 0; i <= 60; i ++){
if(tt == 0) break;
if(f1[i] != 1 && f2[i] != 1){
f1[i] = 1;
f2[i] = 1;
tt --;
}
}
if(tt){
cout << "-1" << endl;
return 0;
}
ll ans1 = 0, ans2 = 0;
for(int i = 0; i <= 60; i ++){
if(f1[i] == 1){
ans1 += fastPow(2, i);
}
}
for(int i = 0; i <= 60; i ++){
if(f2[i] == 1){
ans2 += fastPow(2, i);
}
}
cout << ans1 << " " << ans2 << endl;
}
return 0;
}
E
就用 set 模拟 S 然后用一个前缀和维护 |S|, 再用一个 idx 数组表示 某个数的上一个数出现再什么位置然后模拟即可,思维量不大,可以自己想一下。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 2e5 + 5;
ll n, q, a[MAXN], s[MAXN], idx[MAXN], ans[MAXN];
int main(){
ios::sync_with_stdio(false);
cin >> n >> q;
set<ll> st;
ll cnt = 0;
for(int i = 1; i <= q; i ++){
cin >> a[i];
if(st.count(a[i])){
st.erase(a[i]);
cnt --;
}
else{
st.insert(a[i]);
cnt ++;
}
s[i] = s[i - 1] + cnt;
if(idx[a[i]]){
ans[a[i]] += (s[i - 1] - s[idx[a[i]] - 1]);
idx[a[i]] = 0;
}
else idx[a[i]] = i;
}
for(int i = 1; i <= n; i ++){
if(idx[i]){
ans[i] += (s[q] - s[idx[i] - 1]);
}
cout << ans[i] << " ";
}
return 0;
}
F
待补......
G
不打算补了。
标签:AtCoder,cnt,const,Beginner,int,ll,long,347,MAXN From: https://www.cnblogs.com/XiaoMo247/p/18106790