A. Digit Minimization
题意:给出一个数n,A和B轮流玩游戏,A先,A每次必须将该数的某一位和另一外交换,B每次操作都要删除掉该数的最后一位,求最后得到的最小数。
思路:我们可以发现当n不是二位数时,不论位数是奇数还是偶数,都能够将最小的那一位数保留到最后,当n是二位数时,输出的那一位数一定是个位上的数字。特判一下即可。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
int n;
void solve(){
cin>>n;
int t=n;
int mn=INF;
int cnt=0;
while(t){
cnt++;
int x=t%10;
mn=min(mn,x);
t/=10;
}
if(cnt==2){
cout<<n%10<<endl;
}else{
cout<<mn<<endl;
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
B. Z mod X = C
题意:给出数a,b,c,要求构造三个数x,y,z使得x mod y = a,y mod z = b,z mod x=c,其中1<=a<b<c<=1e8。
思路:我们可以让x<y<z,这样能够依次构造,那么要使z mod x = c,那么z一定是c,要使y mod z = b,那么y就可以是b+c,同理,x=a+b+c。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,c;
void solve(){
cin>>a>>b>>c;
cout<<a+b+c<<' '<<b+c<<' '<<c<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
C. Column Swapping
题意:给出一个矩阵,要求每一行都是不下降序列,如果某一行的两列不满足要求,那么可以将这两列交换,注意:是全部交换。且只能操作一次。问是否能满足每行都是不下降序列。
思路:用一个矩阵复制当前矩阵,然后每行依次排序,再依次对比,如果发现有两列交换,那么就交换一次,然后再检查每一行是否满足题意即可。
模拟题好难写,看了一个佬的代码学习的。对于我一个小萌新,学到了好多。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
int n,m;
void Swap(int x,int y,vector<vector<int>>&a){
for(int i=0;i<n;i++) swap(a[i][x],a[i][y]);
return ;
}
void solve(){
cin>>n>>m;
vector<vector<int>>a(n,vector<int>(m));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>a[i][j];
}
}
vector<vector<int>>b=a;
bool ok=0;
set<int> se;
for(int i=0;i<n;i++){
sort(b[i].begin(),b[i].end());
for(int j=0;j<m;j++){
if(a[i][j]!=b[i][j]){
se.insert(j);
}
if(se.size()==2){
ok=1;
break;
}
}
if(ok) break;
}
if(!ok){
cout<<1<<' '<<1<<endl;
return ;
}
vector<int> pos;
for(auto i:se){
pos.push_back(i);
}
Swap(pos[0],pos[1],a);
for(int i=0;i<n;i++){
for(int j=0;j<m-1;j++){
if(a[i][j]>a[i][j+1]){
cout<<-1<<endl;
return ;
}
}
}
cout<<pos[0]+1<<' '<<pos[1]+1<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
D. Traps
题意:有n个陷阱,你只有m次跳跃陷阱的机会,不跳跃就意味着你会受到伤害a[i],如果你使用了跳跃这个陷阱,那么后面的陷阱伤害值都会+1,求最少对你造成的伤害值。
思路:贪心,假设现在你在第i个陷阱,你还有j次跳跃的机会,那么当前这个陷阱是否跳过取决于a[i]-(n-i-(j-1))的正负,变形得到a[i]+i-(n-j+1),其实n-j+1是不变的,所以只需要维护a[i]+i,然后排序即可。(n-i)表示i陷阱后面还有多少个陷阱,他们对你造成的伤害值,以及你要跳跃j-1个陷阱,那么他们就不会对你额外造成伤害。详情见代码。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
int n,k,a[N],b[N];
void solve(){
cin>>n>>k;
ll ans=0;
for(int i=1;i<=n;i++){
cin>>a[i];
ans+=a[i];
}
for(int i=1;i<=n;i++){
b[i]=a[i]+i;
}
sort(b+1,b+n+1);
for(int i=0;i<k;i++){
ans+=n-i;
}
for(int i=n;i>n-k;i--){
ans-=b[i];
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}