Codeforces Round #843 (Div. 2)(较难场)A1-D题解
A. Gardener and the Capybaras (easy or hard version)
分类讨论即可。
如果第一个字符串以 \(a\) 开头,我们先考虑找一个在中间的 \(b\), 如果存在,则从这个 \(b\) 一直到倒数第二个字符规定为第二个字符串,确保其为最大的。如果不存在这个 \(b\), 那么就是除了最后一个字符全都一定是 \(a\), 那么直接把第二个字符串规定为第二个字符 \(a\) 即可,确保其为最小的。
第一个字符串以 \(b\) 开头时同理。
这样就一次性解决了 \(easy\) 和 \(hard version\)。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int main(){
// freopen("hh.txt", "r", stdin);
int T; cin >> T;
while(T--){
string s;
cin >> s;
string a = "", b = "", c = "";
if(s[0] == 'b'){
int pos = s.length();
for(int i = 0; i < s.length(); i++){
if(s[i] == 'a'){
pos = i;
break;
}
}
if(pos < s.length() - 1){
cout << s.substr(0, pos) << " ";
cout << s[pos] << " ";
cout << s.substr(pos + 1, s.length() - pos - 1);
cout << endl;
}
else cout << s[0] << " " << s[1] << " " << s.substr(2, s.length() - 2) << endl;
}
else if(s[0] == 'a'){
int pos = s.length();
for(int i = 0; i < s.length(); i++){
if(s[i] == 'b'){
pos = i;
break;
}
}
if(pos < s.length() - 1){
cout << s.substr(0, pos) << " ";
cout << s.substr(pos, s.length() - 1 - pos) << " ";
cout << s[s.length() - 1];
cout << endl;
}
else cout << s[0] << " " << s[1] << " " << s.substr(2, s.length() - 2) << endl;
}
}
return 0;
}
B. Gardener and the Array
首先题目没有规定子串的长度。那么我们直接把所有的数字先全部 或 在一起。如果能找到某一个数字,将其删去后不会影响最终与在一起的结果,那么就是 \(Yes\)。否则就是 \(No\)。
补充:获取整体的结果一定是不亏的。因为这是数字越多,删数字的要求也约"宽松"。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
vector <int> G[200010];
int main(){
// freopen("hh.txt", "r", stdin);
int T; cin >> T;
while(T--){
int n; cin >> n;
map <int, int> num;
bool ans = 0;
for(int i = 1; i <= n; i++){
G[i].clear();
int k; cin >> k;
for(int j = 1; j <= k; j++){
int p; cin >> p;
num[p]++;
G[i].push_back(p);
}
}
for(int i = 1; i <= n; i++){
bool flag = 1;
for(auto it : G[i]){
if(num[it] <= 1) flag = 0;
}
ans |= flag;
}
if(ans) puts("YES");
else puts("NO");
}
return 0;
}
C. Interesting Sequence
首先注意到这是一个 与 操作,那么当我们从高到低遇到某一位 \(n\) 为 \(1\) 但 \(x\) 为 \(0\) 时,这一位我们的 \(ans\) 一定只能填 \(0\)。但是我们要保证大小关系,所以将这一位前移保证答案比原数字大。这一位后面的全部抹零即可。(之后的数字无论如何增加,最终答案这一位永远都是 \(0\), 所以不用继续考虑别的情况。)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100
#define ll long long
#define int long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
ll n;
ll x;
signed main(){
// freopen("hh.txt", "r", stdin);
int T; read(T);
while(T--){
read(n), read(x);
bitset <N> a(n);
bitset <N> b(x);
if(a == b){
cout << a.to_ullong() << endl;
continue;
}
if(x > n){
puts("-1");
continue;
}
bool flag = 0;
ll sum = 0;
for(int i = 63; i >= 1; i--){
if(((1ll << (i - 1)) & n) != 0){
if(((1ll << (i - 1)) & x) == 0){
if(((sum + (1ll << i)) & x )== x){
cout << sum + (1ll << (i)) << endl;
flag = 1;
}
break;
}
sum += (1ll << (i - 1));
}
}
if(!flag) puts("-1");
}
return 0;
}
D. Friendly Spiders
这题可以采用分解质因数的方法来解。可以看到,所有蜘蛛间的关系形成了一张图,如果我们能建出一张图,那么求一次最短路便能解决该问题。
下面考虑如何建图。如果对原数字进行暴力建图,首先边数会非常大,其次就是两两枚举求 \(GCD\) 的过程也是显然过不去的。
那么,就引出了分解质因数。不难发现,所有数字的质因数是有限的,而且 \(a_i\) 的范围也较小。例如,我们如果将 \(20\) 分解为 \(2\) 和 \(5\), 只需要将 \(20\) 对 \(2\) 和 \(5\) 连边,再将 \(4\) 对 \(2\) 连边,便完成了我们的建图操作。这样子做可以极大的减少我们的建边所需时间以及图的边数。同时也记得将数字与自己连边(质数)。边权全部设为 \(1\), 最终答案除以 \(2\) 即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 2000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
struct node{
int u, v, w, next;
} t[N << 1];
int head[N << 1];
int bian = 0;
inline void addedge(int u, int v, int w){
t[++bian] = (node){u, v, w, head[u]}, head[u] = bian;
return ;
}
int n;
int a[N];
set <int> s;
map <int, int> g;
set <int> G[N >> 1];
int S, T;
struct point{
ll d;
int id;
bool operator < (const point &a) const{
return d > a.d;
}
} ;
auto cmp = [](point a, point b){return a.d > b.d; };
ll dis[N];
bool vis[N];
int pre[N];
void dij(int S, int T){
priority_queue <point> q;
memset(dis, 0x3f3f3f3f, sizeof(dis));
dis[S] = 0;
q.push((point){0, S});
while(!q.empty()){
int u = q.top().id;
q.pop();
if(!vis[u]){
vis[u] = 1;
for(int i = head[u]; i; i = t[i].next){
int v = t[i].v;
if(dis[v] > dis[u] + t[i].w){
dis[v] = dis[u] + t[i].w;
pre[v] = u;
if(!vis[v]) q.push((point){dis[v], v});
}
}
}
}
return ;
}
int ans[N];
signed main(){
read(n);
for(int i = 1; i <= n; i++)
read(a[i]);
int id = n;
for(int i = 1; i <= n; i++)
g[a[i]] = ++id;
for(int i = 1; i <= n; i++){
vector <int> h;
for(int j = 2; j * j <= a[i]; j++){
if(a[i] % j == 0) h.push_back(j), h.push_back(a[i] / j);
}
h.push_back(a[i]);
sort(h.begin(), h.end());
int tmp = a[i];
vector<int>::iterator it = h.begin();
while(tmp != 1){
if(tmp % *it == 0){
tmp /= *it;
s.insert(*it);
G[i].insert(*it);
}
else it++;
}
}
for(auto it : s){
g[it] = ++id;
}
for(int i = 1; i <= n; i++){
for(auto it : G[i]){
addedge(i, g[it], 1);
addedge(g[it], i, 1);
}
}
read(S), read(T);
dij(S, T);
if(!vis[T]){
puts("-1");
}
else{
int num = 0;
cout << dis[T] / 2 + 1 << endl;
int now = T;
while(pre[now]){
if(now <= n) ans[++num] = now;
now = pre[now];
}
printf("%d ", S);
for(int i = num; i; i--)
printf("%d ", ans[i]);
}
return 0;
}