Codeforces Round #761 (Div. 2)
A - Forbidden Subsequence
分析:
- 只有当 T=“abc”,且主串排完序后,有"abc"在子序列的时候,需要将 bc 换一下位置
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char s[N];
int vis[55];
signed main()
{
int T;
cin>>T;
while(T--)
{
memset(vis,0,sizeof(vis));
string sr;
cin>>s>>sr;
int len=strlen(s);
sort(s,s+len);
string ss;
for(int i=0;i<len;i++)
{
int u=s[i]-'a';
if(!vis[u])
{
ss+=s[i];
vis[u]=1;
}
}
if(sr=="abc" && ss.size()>2 && ss[2]==sr[2] && ss[0]==sr[0] && ss[1]==sr[1])
{
int b=0,c=0;
for(int i=0;i<len;i++)
{
if(s[i]=='b') b++;
if(s[i]=='c') c++;
}
for(int i=0;i<len;i++)
{
if(s[i]=='a') cout<<'a';
}
for(int i=0;i<c;i++) cout<<'c';
for(int i=0;i<b;i++) cout<<'b';
for(int i=0;i<len;i++) if(s[i]!='a' && s[i]!='b' && s[i]!='c') cout<<s[i];
cout<<endl;
}
else cout<<s<<endl;
}
}
B - GCD Problem
分析:
- 分三类情况考虑
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char s[N];
int vis[55];
signed main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int a,b,c;
if(n%2==0) //1. n为偶数
{
c=1;
a=(n-1)/2;
b=a+1;
cout<<a<<' '<<b<<' '<<c<<endl;
}
else
{
c=1;
n-=1;
if((n/2)&1) // 2. n为奇数,且n/2为奇数
{
a=n/2-2;
b=n/2+2;
}
else // 3. n为奇数,且n/2为偶数
{
a=n/2-1;
b=n/2+1;
}
cout<<a<<' '<<b<<' '<<c<<endl;
}
}
}
C - Paprika and Permutation
分析:
-
首先,要先发现一个规律:对于一个数m,其模余之后最大为 ( m − 1 ) / 2 (m-1)/2 (m−1)/2 , 即:m能变成 1 ~ ( m − 1 ) / 2 (m-1)/2 (m−1)/2 外加本身 m
-
然后就是分三类讨论:
- a [ i ] < = n a[i]<=n a[i]<=n :第一次出现,直接拿走,不用变,之后再次出现,要变成更小的数, b [ ( a [ i ] − 1 ) / 2 ] b[(a[i]-1)/2] b[(a[i]−1)/2] 表示:最大能变成 ( a [ i ] − 1 ) / 2 (a[i]-1)/2 (a[i]−1)/2 的数的个数
- a [ i ] > 2 n a[i]>2n a[i]>2n :模余能变成 1~ n 的所有数,直接 b [ n ] + + b[n]++ b[n]++
- n < a [ i ] < = 2 n n<a[i]<=2n n<a[i]<=2n :一般情况
-
统计出所有的 b [ i ] b[i] b[i] ,然后跑一遍前缀和,再加过程判断即可
因为后面的 b [ i ] b[i] b[i] ,一定能转换成前面的,所以前缀和就是到当前的 i 能转换的个数,若 s u m > i sum>i sum>i , 则失败
最后,还要再判一遍 s u m = = n sum==n sum==n ( b [ 0 ] b[0] b[0] 可能不为0 )
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],b[N],vis[N];
signed main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int cnt=0;
for(int i=1;i<=n;i++) b[i]=vis[i]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]<=n)
{
vis[a[i]]++;
if(vis[a[i]]>1)
{
b[(a[i]-1)/2]++;
}
else
{
b[a[i]]++; // 注意第一次出现,a[i]要记一次 次数
cnt++;
}
}
else if(a[i]>2*n)
{
b[n]++;
}
else
{
b[(a[i]-1)/2]++;
}
}
int sum=0,fg=1;
for(int i=1;i<=n;i++)
{
sum+=b[i];
//
if(sum>i)
{
fg=0;
break;
}
}
if(sum!=n) fg=0;
if(fg)
{
cout<<n-cnt<<endl;
}
else cout<<"-1\n";
}
}