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
题意:给两字符串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
题意:假设初始时的数组为 [ 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;
}