Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)ABCD题解

Harbour.Space Scholarship Contest 2021-2022 open for everyone, rated, Div. 1 + Div. 2

A. Digits Sum

地址: A. Digits Sum

题意:找到1到n中有多少数x符合 S(x+1)<S(x),其中S(x)是以十进制数字x的位数之和。例如,S(5)=5,S(10)=1,S(322)=7。

题解:可以发现只有x的个位数为9才会符合S(x+1)<S(x)

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Cans cout<<ans<<endl;
#define Cneg {cout<<-1<<endl;return;}
#define Cno {cout<<"NO"<<endl;return;}
#define Cyes {cout<<"YES"<<endl;return;}
#define mem(a,n) memset(a,n,sizeof(a)) 
#define gcd(a,b) __gcd(a,b) 
#define lcm(a,b) a*b/(gcd(a,b)) 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define bug(x) cout<<"---"<<x<<endl;
priority_queue <int,vector<int>,less<int> > QM;
const int eps=1319,mod= 998244353;
const int maxn= 1e5+5;
const int INF= 0x3f3f3f3f;
inline ll Qpow(ll a,ll b){ll s=1;while(b){if(b&1){s=(s*a)%mod;}a=a*a%mod;b>>=1;}return s;}
inline ll Qinv(ll a){return Qpow(a,mod-2);}
 
void solve(){
	ll n;
	cin>>n;
	ll ans=(n+1)/10;
	cout<<ans<<endl; 
}
int main(int argc,char *argv[]){
	int _; cin >> _;
	while(_--)
	solve();
	return 0;
}

B. Reverse String

地址: B. Reverse String

题意:给两字符串S、T,有一指针从S的某字符先向右移动再向左移动,问是否某一处指针通过移动后经过的字符串与T相同

题解:由于题目数据范围较小, s (1≤|s|≤5001≤|s|≤500) , t (1≤|t|≤2⋅|s|−11≤|t|≤2⋅|s|−1). 可以暴力寻找指针的起点和方向改变的转折点,判断指针路径与T是否相同

代码:

#include<bitsdc++.h>
using namespace std;
#define ll long long
#define Cans cout<<ans<<endl;
#define Cneg {cout<<-1<<endl;return;}
#define Cno {cout<<"NO"<<endl;return;}
#define Cyes {cout<<"YES"<<endl;return;}
#define mem(a,n) memset(a,n,sizeof(a)) 
#define gcd(a,b) __gcd(a,b) 
#define lcm(a,b) a*b/(gcd(a,b)) 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define bug(x) cout<<"---"<<x<<endl;
priority_queue <int,vector<int>,less<int> > QM;
const int eps=1319,mod= 998244353;
const int maxn= 1e5+5;
const int INF= 0x3f3f3f3f;
inline ll Qpow(ll a,ll b){ll s=1;while(b){if(b&1){s=(s*a)%mod;}a=a*a%mod;b>>=1;}return s;}
inline ll Qinv(ll a){return Qpow(a,mod-2);}

char str1[502],str2[1002]; 
void solve(){
	scanf("%s %s",str1+1,str2+1);
	int n=strlen(str1+1),m=strlen(str2+1);
	for(int i=1;i<=n;i++){//枚举起点 
		for(int j=i;j<=n;j++){//枚举转折点 
			if(m>j+(j-i))continue;//最长能得到的串不能比str2短 
			int pos=1,flag=1;
			for(int k=i;k<=j;k++){//向右移动 
				if(str1[k]!=str2[pos++]){
					flag=0;
					break;
				}
			}
			for(int k=j-1;k>=0&&pos<=m;k--){//向左移动 
				if(str1[k]!=str2[pos++]){
					flag=0;
					break;
				}
			}
			if(flag)Cyes
		}
	}
	Cno
}
int main(int argc,char *argv[]){
	int _; cin >> _;
	while(_--)
	solve();
	return 0;
}

C. Penalty

地址: C. Penalty

题意:两只队伍轮流踢点球共10个球,每次球有3种情况:进、没进和都有可能,通过给出的10球情况,判断最少几轮结束

题解:遍历10次进球情况,每次更新两队目前的最少得分、最多得分以及剩余次数、如果一队获得最大得分超过另一队最少得分+剩余场次则停止

代码:

#include<bitsdc++.h>
using namespace std;
#define ll long long
#define Cans cout<<ans<<endl;
#define Cneg {cout<<-1<<endl;return;}
#define Cno {cout<<"NO"<<endl;return;}
#define Cyes {cout<<"YES"<<endl;return;}
#define mem(a,n) memset(a,n,sizeof(a)) 
#define gcd(a,b) __gcd(a,b) 
#define lcm(a,b) a*b/(gcd(a,b)) 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define bug(x) cout<<"---"<<x<<endl;
priority_queue <int,vector<int>,less<int> > QM;
const int eps=1319,mod= 998244353;
const int maxn= 1e5+5;
const int INF= 0x3f3f3f3f;
inline ll Qpow(ll a,ll b){ll s=1;while(b){if(b&1){s=(s*a)%mod;}a=a*a%mod;b>>=1;}return s;}
inline ll Qinv(ll a){return Qpow(a,mod-2);}
 
void solve(){
	string str;
	cin>>str;
//	min表示到当前最少得分,max表示到当前最多得分,sy表示剩余场次 
	int mina=0,maxa=0,sya=5;
	int minb=0,maxb=0,syb=5;
	
	int ans=1;
	for(;ans<=10;ans++){
		if(ans%2==1){
			if(str[ans-1]=='1')mina++,maxa++;
			if(str[ans-1]=='?')maxa++;
			sya--;
		}
		if(maxb>mina+sya||maxa>minb+syb){//当前获得最大得分超过另一队最少得分+剩余场次则停止 
			cout<<ans<<endl;
			return;
		}
		if(ans%2==0){
			if(str[ans-1]=='1')minb++,maxb++;
			if(str[ans-1]=='?')maxb++;
			syb--;
		}
		if(maxb>mina+sya||maxa>minb+syb){
			cout<<ans<<endl;
			return;
		}
	}
	cout<<10<<endl;
}
int main(int argc,char *argv[]){
	int _; cin >> _;
	while(_--)
	solve();
	return 0;
}

D. Backspace

地址: D. Backspace

题意:给出两个字符串S、T,想通过输出S得到T,输出过程中可以通过按退格键覆盖当前及前一个字符,问是否能得到T

题解:如果T比S长直接输出NO,否则从后往前匹配,注意当某一位置匹配失败后S要向前移动两个字符

代码:

#include<bitsdc++.h>
using namespace std;
#define ll long long
#define Cans cout<<ans<<endl;
#define Cneg {cout<<-1<<endl;return;}
#define Cno {cout<<"NO"<<endl;return;}
#define Cyes {cout<<"YES"<<endl;return;}
#define mem(a,n) memset(a,n,sizeof(a)) 
#define gcd(a,b) __gcd(a,b) 
#define lcm(a,b) a*b/(gcd(a,b)) 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define bug(x) cout<<"---"<<x<<endl;
priority_queue <int,vector<int>,less<int> > QM;
const int eps=1319,mod= 998244353;
const int maxn= 1e5+5;
const int INF= 0x3f3f3f3f;
inline ll Qpow(ll a,ll b){ll s=1;while(b){if(b&1){s=(s*a)%mod;}a=a*a%mod;b>>=1;}return s;}
inline ll Qinv(ll a){return Qpow(a,mod-2);}
 
char str1[maxn],str2[maxn]; 
void solve(){
	scanf("%s %s",str1,str2);
	int n=strlen(str1),m=strlen(str2);
	if(n<m) Cno
	int i=n-1,j=m-1;//从后往前匹配 
	while(i>=0&&j>=0){
		if(str1[i]==str2[j])i--,j--;
		else i-=2;//每一次按空格会减少两个字符 
	}
	if(j==-1) Cyes
	else Cno
}
int main(int argc,char *argv[]){
	int _; cin >> _;
	while(_--)
	solve();
	return 0;
}

E. Permutation Shift

地址: E. Permutation Shift

题意:假设初始时的数组为 [ 1 , 2 , 3 , . . . , n ]同时k为偏移量,则原数组会循环右移 k个单位,假设 k = 3 , n = 5 ,则偏移后的数组为 [ 3 , 4 , 5 , 1 , 2 ]
现在给出一个数组a,问能否通过至多m次交换,使得其变成偏移 k 个单位后的数组,如果可以的话,哪些 k是符合条件的

题解:
先记录下每个数偏移多少次恰好使a[i]=i,a[i]>i时需要n+i-a[i]次,a[i]<=i时需要i-a[i]次;再统计每个偏移量出现的次数,这样就得到了偏移x次后有多少个a[i]恰好等于i。
之后假设偏移x次后有vis[x]个a[i]恰好等于i,那么剩下n-vis[i]个元素需要交换,至少需要交换(n-vis[i]+1)/2次,如果(n-vis[i]+1)/2>m,就考虑下一个偏移量x+1,否则判断一下当前偏移量最少需要交换几次

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Cans cout<<ans<<endl;
#define Cneg {cout<<-1<<endl;return;}
#define Cno {cout<<"NO"<<endl;return;}
#define Cyes {cout<<"YES"<<endl;return;}
#define mem(a,n) memset(a,n,sizeof(a)) 
#define gcd(a,b) __gcd(a,b) 
#define lcm(a,b) a*b/(gcd(a,b)) 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define bug(x) cout<<"---"<<x<<endl;
priority_queue <int,vector<int>,less<int> > QM;
const int eps=1319,mod= 1e9+7;
const int maxn= 3e5+5;
const int INF= 0x3f3f3f3f;
inline ll Qpow(ll a,ll b){ll s=1;while(b){if(b&1){s=(s*a)%mod;}a=a*a%mod;b>>=1;}return s;}
inline ll Qinv(ll a){return Qpow(a,mod-2);}
 
int n,m;
int a[maxn],vis[maxn];
vector<int> k;
bool check(int k){
	int b[maxn],ans=0;
	for(int i=1;i<=n;i++){
		b[i]=a[i]+k;
		if(b[i]>n) b[i]%=n;
	}
//	for(int i=1;i<=n;i++) cout<<b[i]<<" ";cout<<endl;
	for(int i=1;i<=n;i++){
		while(b[i]!=i){
			swap(b[b[i]],b[i]);
			ans++;
		}
	}
	return ans<=m;
}
void solve(){
	cin>>n>>m;
	k.clear();
	for(int i=0;i<=n;i++) vis[i]=0;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) {
		if(a[i]>i) vis[n+i-a[i]]++;
		else vis[i-a[i]]++;
	}
	
//	for(int i=0;i<n;i++) cout<<vis[i]<<" ";
//	cout<<endl;
	
	int ans=0;
	for(int i=0;i<n;i++) 
		if((n-vis[i]+1)/2<=m&&check(i)) 
			k.push_back(i); 
		
	cout<<k.size()<<" ";
	for(int i=0;i<k.size();i++) cout<<k[i]<<" ";
	cout<<endl;
}
int main(int argc,char *argv[]){
//	init();
	int _; cin >> _;
	while(_--)
	solve();
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温柔说给风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值