A. Forbidden Subsequence
题目详情
给定字符串 S S S 和 T T T,由小写英文字母组成。保证 T T T 是字符串 a b c abc abc 的排列。
找到字符串 S ′ S' S′,即 S S S 的字典序最小排列,使得 T T T 不是 S ′ S' S′ 的子序列。
如果两个字符串中每个不同字符的出现次数相同,则字符串 a a a 是字符串 b b b 的排列。
如果可以通过删除多个(可能为零或所有)元素从 b b b 中获得 a a a,则字符串 a a a 是字符串 b b b 的子序列。
当且仅当以下条件之一成立时,字符串 a a a 在字典序上小于字符串 b b b:
a是b的前缀,但 a ≠ b a≠b a=b;
在 a a a 和 b b b 不同的第一个位置,字符串 a a a 有一个字母在字母表中比 b b b 中的相应字母出现得更早。
输入
每个测试包含多个测试用例。第一行包含一个整数 t ( 1 ≤ t ≤ 1000 ) t (1≤t≤1000) t(1≤t≤1000)——测试用例的数量。测试用例的描述如下。
每个测试用例的第一行包含一个字符串 S ( 1 ≤ ∣ S ∣ ≤ 100 ) S (1≤|S|≤100) S(1≤∣S∣≤100),由小写英文字母组成。
每个测试用例的第二行包含一个字符串 T T T,它是字符串 abc 的排列。 (因此, ∣ T ∣ = 3 |T|=3 ∣T∣=3)。
注意 ∣ S ∣ |S| ∣S∣的总和没有限制跨所有测试用例。
输出
对于每个测试用例,输出单个字符串 S ′ S' S′,即 S S S 的字典序最小排列,使得 T T T 不是 S ′ S' S′ 的子序列。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
const int maxn=1e6+5;
void solve(){
string s, t, s1;
cin >> s;
cin >> t;
sort(s.begin(), s.end());
int a[5]={
0};
for (int i = 0; i < s.length();i++){
if(s[i]=='a')
a[0]++;
if(s[i]=='b')
a[1]++;
if(s[i]=='c')
a[2]++;
}
if(a[0]&&a[1]&&a[2]&&t=="abc"){
for (int i = 0; i < a[0];i++)
cout << "a";
for (int i = 0; i < a[2];i++)
cout << "c";
for (int i = 0; i < a[1];i++)
cout << 'b';
// cout << "!";
cout << s.substr(a[0] + a[1] + a[2]) << endl;
}else{
cout << s << endl;
}
}
int main(){
ios::sync_with_stdio(0);
int t;
cin >> t ;
while(t--){
solve();
}
return 0;
}
B. GCD Problem
题目详情
给定一个正整数 n。 找出三个不同的正整数 a 、 b 、 c a、b、c a、b、c,使得 a + b + c = n a+b+c=n a+b+c=n 和 g c d ( a , b ) = c gcd(a,b)=c gcd(a,b)=c,其中 g c d ( x , y ) gcd(x,y) gcd(x,y) 表示整数 x 和 y 的最大公约数 (GCD)。
输入
输入由多个测试用例组成。 第一行包含一个整数 t ( 1 ≤ t ≤ 1 0 5 ) t (1≤t≤10^5) t(1≤t≤105)——测试用例的数量。 测试用例的描述如下。
每个测试用例的第一行也是唯一一行包含一个整数 n ( 10 ≤ n ≤ 1 0 9 ) n (10≤n≤10^9) n(10≤n≤109)。
输出
对于每个测试用例,输出满足要求的三个不同的正整数 a 、 b 、 c a、b、c a、b、c。 如果有多个解决方案,您可以打印任何一个。 我们可以证明答案总是存在的。
coed:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
const int maxn = 1e6 + 5;
ll gcd(ll a, ll b){
return a % b == 0 ? b : gcd(b, a % b);
}
void solve(){
ll n, i;
cin >> n;
if (n % 2 == 0){
cout << (n - 1) / 2 << " " << (n - 1) / 2 + 1 << " " << 1 << endl;
}
else{
if ((n - 1) / 2 % 2 == 0){
cout << (n - 1) / 2 - 1 << " " << (n - 1) / 2 + 1 << " " << 1 << endl;
}
else{
cout << (n - 1) / 2 - 2 << " " << (n - 1) / 2 + 2 << " " << 1 << endl;
}
}
//cout << 1 << " " << n - 2 << " " << 1 << endl;
}
int main()
{
ios::sync_with_stdio(0);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C. Paprika and Permutation
题目详情
辣椒粉喜欢排列组合。她有一个数组 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an。她想让数组成为整数 1 到 n 的排列。
为了实现这个目标,她可以对数组进行操作。在每次运算中她可以选择两个整数i ( 1 ≤ i ≤ n ) (1≤i≤n) (1≤i≤n)和 x ( x > 0 ) x(x>0) x(x>0),然后执行 a i : = a i m o d x a_i:=a_i mod x ai:=aimodx(即用 a i a_i ai除以x的余数替换 a i a_i ai)。在不同的操作中,选择的 i 和 x 可以不同。
确定使数组成为整数 1 到 n 的排列所需的最少操作次数。如果不可能,则输出-1。
排列是由以任意顺序从 1 到 n 的 n 个不同整数组成的数组。例如,[2,3,1,5,4]
是排列,但 [1,2,2]
不是排列(2 在数组中出现两次),[1,3,4]
也不是排列排列(n=3 但数组中有 4 个)。
输入
每个测试包含多个测试用例。第一行包含一个整数 t ( 1 ≤ t ≤ 1 0 4 ) t (1≤t≤10^4) t(1≤t≤104)——测试用例的数量。测试用例的描述如下。
每个测试用例的第一行包含一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n (1≤n≤10^5) n(1≤n≤105)。
每个测试用例的第二行包含 n 个整数 a 1 , a 2 , . . . , a n 。 ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,...,a_n。 (1≤a_i≤10^9) a1,a2,...,an。(1≤ai≤109)。
保证所有测试用例的 n 总和不超过 2 ⋅ 1 0 5 2⋅10^5 2⋅105。
输出
对于每个测试用例,输出使数组成为整数 1 到 n 的排列所需的最少操作次数,如果不可能,则输出 -1。
解题思路:
关键:如果查询(a,b,c)的结果≠查询(b,c,d)的结果,由于b和c是共同的,玩家a和d有不同的角色。 此外,如果查询的结果 (a,b,c) = 1,则玩家 a 是船员(玩家 d 是冒名顶替者),反之亦然。
第一步是查询玩家 (1,2,3), (2,3,4), …, (n−1,n,1), (n,1,2)。
如果任意两个相邻查询(或查询 (1,2,3) 和 (n,1,2))的结果不同,我们立即知道只包含在一个查询中的两个玩家的角色——一个是 队友,一个是冒名顶替的。 由于冒名顶替者 k 和船员 nk 的数量满足 k>n3 和 nk>n3,因此必须存在一对不同的相邻查询。
在我们知道一名船员和一名冒名顶替者(让我们称他们为 a、d)后,我们可以查询这两名玩家与其他玩家中的每一个。 如果查询 (a,d,x)(1≤x≤n,x≠a 和 x≠d)返回 0,则玩家 x 是冒名顶替者,否则玩家 x 是队友。
总共使用了 2n−2 个查询。
coed:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
const int N=1e6+5;
int n,tot;
int a[N],ocr[N];
inline void solve(){
cin >>n;
for (int i=1;i<=n;i++) ocr[i]=0;
tot=0;
for (int i=1,t;i<=n;i++){
cin >>t;
if (t<=n&&!ocr[t]) ocr[t]=1;
else a[tot++]=(t-1)/2;
}
int ans=tot;
sort(a,a+tot);
for (int i=n;i>=1;i--){
if (ocr[i]) continue;
else {
if (a[--tot]<i){
cout <<"-1\n";
return;
}
}
}
cout <<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0);
int t;
cin >> t ;
while(t--){
solve();
}
return 0;
}