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(1t1000)——测试用例的数量。测试用例的描述如下。

每个测试用例的第一行包含一个字符串 S ( 1 ≤ ∣ S ∣ ≤ 100 ) S (1≤|S|≤100) S(1S100),由小写英文字母组成。

每个测试用例的第二行包含一个字符串 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 abc,使得 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(1t105)——测试用例的数量。 测试用例的描述如下。

每个测试用例的第一行也是唯一一行包含一个整数 n ( 10 ≤ n ≤ 1 0 9 ) n (10≤n≤10^9) n(10n109)

输出

对于每个测试用例,输出满足要求的三个不同的正整数 a 、 b 、 c a、b、c abc。 如果有多个解决方案,您可以打印任何一个。 我们可以证明答案总是存在的。

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) 1in x ( x > 0 ) x(x>0) xx>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(1t104)——测试用例的数量。测试用例的描述如下。

每个测试用例的第一行包含一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n (1≤n≤10^5) n(1n105)

每个测试用例的第二行包含 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(1ai109)

保证所有测试用例的 n 总和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

输出

对于每个测试用例,输出使数组成为整数 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;
}