A
Gardener and the Capybaras (hard version)
题意:给定一个由字母a和b组成的字符串,将该串分成3部分,使得中间部分字典序最小或最大。
思路:在除了两端的位置找一个a,若存在,此时中间部分字典序最小。否则,去掉头和尾,中间部分全b,字典序最大。
#include <bits/stdc++.h>
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
string s;
void solve()
{
cin>>s;
int pos=-1;
int n=s.length();
for(int i=1;i<n-1;i++)
{
if(s[i]=='a')
{
pos=i;
break;
}
}
if(pos!=-1) cout<<s.substr(0,pos)<<' '<<'a'<<' '<<s.substr(pos+1)<<'\n';
else cout<<s[0]<<' '<<s.substr(1,n-2)<<' '<<s[n-1]<<'\n';
}
signed main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
B
题意:给定长度为n的数组c,问是否存在两个不同的子序列,使得两个子序列内所有数or操作后相等。
思路:我们让其中一个序列包含的数尽可能的多,我们让它包含所有的数,然后可以将该序列中可有可无的数去除掉作为另一序列。对于一个数ci,若该数所有位上出现的次数都大于1,那么这个数就是可有可无的。序列a包含所有的数,序列b除去ci这个数的所有的数
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ios cin.sync_with_stdio(false)
#define PII pair<int,int>
typedef long long ll;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
void solve()
{
cin>>n;
vector<vector<int>>v(n+1);
map<int,int>cnt;
for(int i=1;i<=n;i++)
{
int k;
cin>>k;
for(int j=1;j<=k;j++)
{
int x;
cin>>x;
v[i].push_back(x);
cnt[x]++;
}
}
bool f=0;
for(int i=1;i<=n;i++)
{
f=1;
for(int j=0;j<v[i].size();j++)
{
if(cnt[v[i][j]]<2)
{
f=0;
break;
}
}
if(f)
{
puts("YES");
return ;
}
}
puts("NO");
}
signed main()
{
ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
C
题意:给定n和x,求最小的m,使得n&(n+1)&...&m==x
思路:我们看每一个二进制位k:
情况1: =0,
=0,对答案没有影响
情况2:=1,
=0,那么在[n,m]的范围内,一定至少存在一个数第k位是0
情况3: =0,
=1,无解
情况4: =1,
=1,那么在[n,m]的范围内,所有数的第k位都是1
若情况4的更高位存在情况2,那么是无解的。
所有的情况2,我们找到最高位出现的情况2,然后看是否存在比这个位小的情况4
#include <bits/stdc++.h>
#define ios cin.sync_with_stdio(false)
#define PII pair<int, int>
#define int long long
typedef long long ll;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
using namespace std;
ll n, x;
int get(ll x)
{
int ret = 0;
while (x)
{
x /= 2;
ret++;
}
return ret;
}
void solve()
{
cin >> n >> x;
if (n == x)
{
cout << n << '\n';
return;
}
if (x > n)
{
cout << -1 << '\n';
return;
}
int p = get(n);
// gao(p);
bool f = 0;
ll pos = 0;
for (int i = p - 1; i >= 0; i--)
{
if ((n >> i) % 2 == 0 && (x >> i & 1))
{
cout << -1 << '\n';
return;
}
if (!f && (n >> i & 1) && (x >> i) % 2 == 0)
{
f = 1;
pos = i;
if (x >> (i + 1) & 1)
{
cout << -1 << '\n';
return;
}
}
else if (f && (x >> i & 1))
{
cout << -1 << '\n';
return;
}
}
ll ans = n >> pos;
ans <<= pos;
ans += 1ll << pos;
cout << ans << '\n';
}
signed main()
{
// ios;
int _t = 1;
cin >> _t;
while (_t--)
solve();
system("pause");
return 0;
}
D
题意:给定n个点,每个点的权值为ai。两个位置[i,j]之间存在长度为1的边当且仅当gcd(ai,aj)>1.问从S到T的最短路。
思路:对于有共同因子的数,他们是可以相互到达的。设共同因子为p,我们可以在a[i]->p建立边长为0的边,p->a[i]建立边长为1的边。
对于一个数,质因子个数是logn级别的,所以图中边的数量为n*logn,点数n+n*logn。
因为边权只有0和1,我们可以用01bfs。同时记录前驱用来输出路径。
#include <bits/stdc++.h>
#define ios cin.sync_with_stdio(false)
#define PII pair<int, int>
typedef long long ll;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
using namespace std;
int n;
int a[N];
int S, T;
vector<PII>g[N*2];
int cnt[N*2];
int pre[N*2];
bool vis[N*2];
bool bfs()
{
deque<int>q;
q.push_back(S);
vis[S]=1;
while(q.size())
{
int u=q.front();
q.pop_front();
if(u==T) return 1;
for(auto [v,w]:g[u])
{
if(vis[v]) continue;
vis[v]=1;
pre[v]=u;
if(w==1) q.push_back(v);
else q.push_front(v);
}
}
return 0;
}
void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
cin >> S >> T;
if (S == T)
{
cout << 1 << '\n';
cout << S << '\n';
return;
}
if (a[S] == a[T])
{
if (a[S]==1)
{
cout << -1 << '\n';
return;
}
else
{
cout << 2 << '\n';
cout << S << ' ' << T << '\n';
return;
}
}
for(int i=1;i<=n;i++)
{
for(int j=2;j*j<=a[i];j++)
{
if(a[i]%j==0)
{
while(a[i]%j==0) a[i]/=j;
g[i].push_back({N+j,0});
g[N+j].push_back({i,1});
}
}
if(a[i]>1)
{
g[i].push_back({N+a[i],0});
g[N+a[i]].push_back({i,1});
}
}
if(!bfs())
{
cout<<-1<<'\n';
return ;
}
vector<int> ret;
int cur = T;
while (cur != S)
{
if (cur <= n)
ret.push_back(cur);
cur = pre[cur];
}
ret.push_back(S);
cout << ret.size() << '\n';
for (int i = ret.size() - 1; i >= 0; i--)
cout << ret[i] << " \n"[i == 0];
}
signed main()
{
// ios;
int _t = 1;
// cin>>_t;
while (_t--)
solve();
system("pause");
return 0;
}