Codeforces Round 925(Div. 3)
文章目录
A. Recovering a Small String
暴搜
一共就三个字母,我们只要每次从第一个字母开始,如果搜满三个字母,且正好总和为n,那么这就是答案,直接返回即可。
时间复杂度: 2 6 3 26^3 263
#include<bits/stdc++.h>
using namespace std;
bool is_yes=0;
void dfs(int n,int pos,string s){
if(is_yes==1)return;
if(pos==4 and n!=0)return;
if(pos==4 and n==0){
cout<<s<<endl;
is_yes=1;
return;
}
for(int i=0;i<26;i++){
if(i<=n){
char c=i+'a';
dfs(n-i-1,pos+1,s+c);
}
}
}
void slove(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
string s;
is_yes=0;
dfs(n,1,s);
}
}
int main(){
slove();
}
B. Make Equal
模拟
算出平均数,然后从1开始,将多了的传递给下一个,直到最后一个,再检查一下第一个和最后一个是否为平均数即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
void slove(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
vector<ll> a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
ll sum=0;
for(int i=1;i<=n;i++){
sum+=a[i];
}
ll ans=sum/n;
for(int i=1;i<=n-1;i++){
if(a[i]>ans){
ll cha=a[i]-ans;
a[i+1]+=cha;
a[i]-=cha;
}
}
bool is_yes=1;
for(int i=1;i<=n;i++){
if(a[i]!=ans){
is_yes=0;
break;
}
}
if(is_yes==1)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
int main(){
slove();
}
C. Make Equal Again
模拟
由于只有一次操作,所以我们只能从两端开始收缩
先记录从1开始,连续相等的个数t1
再记录从n开始,连续相等的个数t2
如果a[1]==a[n],那么答案就是n-t1-t2
如果不等,那么取最小的 min(n-t1,n-t2)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
void slove(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
int t1=a[1];
int pos1=1;
for(int i=2;i<=n;i++){
if(a[i]==t1)pos1++;
else break;
}
int t2=a[n];
int pos2=1;
for(int i=n-1;i>=1;i--){
if(a[i]==t2)pos2++;
else break;
}
if(t1==t2){
int ans= max(0,n-pos2-pos1);
cout<<ans<<endl;
}
else{
int ans= min(n-pos1,n-pos2);
cout<<ans<<endl;
}
}
}
int main(){
slove();
}
D. Divisible Pairs
数论同余
设 a i = p 1 x + r 1 , a j = p 2 x + r 2 a_i=p_1x+r_1\ ,a_j=p_2x+r_2 ai=p1x+r1 ,aj=p2x+r2
则 a i + a j = p 1 x + r 1 + p 2 x + r 2 a_i+a_j=p_1x+r_1\ +p_2x+r_2 ai+aj=p1x+r1 +p2x+r2
所以只需要满足 r 1 + r 2 ≡ 0 ( m o d x ) r_1+r_2\equiv0(mod\ x) r1+r2≡0(mod x)
同理
设 a i = p 1 y + r 1 , a j = p 2 y + r 2 a_i=p_1y+r_1\ ,a_j=p_2y+r_2 ai=p1y+r1 ,aj=p2y+r2
则 a i − a j = p 1 x + r 1 − p 2 x − r 2 a_i-a_j=p_1x+r_1\ -p_2x-r_2 ai−aj=p1x+r1 −p2x−r2
只需要 r 1 − r 2 ≡ 0 ( m o d y ) r_1-r_2\equiv0(mod\ y) r1−r2≡0(mod y)
对于x,我们需要特判一下r1=r2=0的情况
一般情况就是 r2=x-r1
对于y,我们只要找 r1=r2的个数就行
开map记录数对,并且倒序输入(因为题目要求i<j)
ps:赛场上没写出来的原因是卡在特判了,我只找了 x-r1的情况
再加上手速比较慢,所以d花了很多时间,导致e差几分钟就能写完。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
void slove(){
int t;
cin>>t;
while(t--){
ll n,x,y;
cin>>n>>x>>y;
vector<ll> a(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
//x意义,y意义,id,个数
map<pair<ll,ll>,int >m;
ll ans=0;
for(int i=n;i>=1;i--){
ll xyu,yyu;
xyu=a[i]%x;
yyu=a[i]%y;
ll t=x-xyu;
if(xyu==0)t=0;
if(m.count({t,yyu}) ){
ans+=m[{t,yyu}];
}
m[{xyu,yyu}]++;
}
cout<<ans<<endl;
}
}
int main(){
slove();
}
E. Anna and the Valentine’s Day Gift
Multiset / 数据结构 / 模拟 /思维
先手Anna,她最优的操作是反转后置0最多的数,使得总位数减少的多。
后手Sasha,需要将后置0最多的数和后置零最少的数合并。
后置零最少的数一定是0,因为Anna每一次操作都会将后置0清空。
所以记录位数之和,然后记录每个数的后置0,并按后置0个数从大到小排序
然后减去奇数次的即可。
嗯。。没错,这是我刚刚写题解的时候想到的,我估计正解就是这样。
我最开始的想法是模拟,将所有数据插入multiset中,然后当sasha操作的时候,取出里面最大的和最小的,合并,然后放回multiset中。
我发现我好蠢啊。
可以看一下两者的内存差距。
下面给出优化版的E题代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
bool cmp(int a,int b){
return a>b;
}
void slove(){
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
vector<int> big(n+1);
vector<int> a(n);
ll sum=0;
for(int i=0;i<n;i++){
ll t;
cin>>t;
int cnt=0; //记录后置0
int bnt=0; //记录位数
ll temp=t;
while(temp){
if(temp%10==0)cnt++;
else break;
temp/=10;
}
while(t){
bnt++;
t/=10;
}
sum+=bnt; //记录总位数
a[i]=cnt; //记录每一个数的后置0个数
}
sort(a.begin(),a.end(),cmp);
for(int i=0;i<n;i++){
if((i+1)&1)sum-=a[i];
}
if(sum-1>=m)cout<<"Sasha"<<endl;
else cout<<"Anna"<<endl;
}
}
int main(){
slove();
}
}
sum+=bnt; //记录总位数
a[i]=cnt; //记录每一个数的后置0个数
}
sort(a.begin(),a.end(),cmp);
for(int i=0;i<n;i++){
if((i+1)&1)sum-=a[i];
}
if(sum-1>=m)cout<<"Sasha"<<endl;
else cout<<"Anna"<<endl;
}
}
int main(){
slove();
}