A. Digit Minimization
分析
每次操作先交换两个数再删去尾端的数,使最后剩余的数最小。
直接判断这个数大于100,每次操作都可以把最小的数留到最后,只有两位数的话只能是个位的数。
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
if(n/100==0)
{
int a=n/10;
int b=n%10;
cout<<b<<endl;
continue;
}
int ans=10;
while(n)
{
int tt=n%10;
ans=min(ans,tt);
n/=10;
if(ans==1) break;
}
cout<<ans<<endl;
}
return 0;
}
B. Z mod X = C
分析
给出a,b,c,找出满足x mod y = a ,y mod z = b ,z mod x = c;的x,y,z。
之前做过类似的题,先做出式子代换,代换为假设z的k为0,其余两个k相同,即可推出x和y的值。
注意:x,y,z的值需要开long long。
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
ll a,b,c;
cin>>a>>b>>c;
ll x,y,z;
z=c;
for(int i=0;i<=1e5;i++)
{
y=i*c+b;
x=i*y+a;;
if(x%y==a&&y%z==b&&z%x==c) break;
}
cout<<x<<" "<<y<<" "<<z<<endl;
}
return 0;
}
C. Column Swapping
分析
只能选择一次两列数,交换他们,使每一行的数都是非递减的。
设需要交换的列的数量为cnt:
当cnt=0,无需交换,可以直接选择交换1 1;
当cnt<=2时,尝试交换两列,并判断交换后,每行的这两列位置的数字是否已与排序后的该位置的数字相等;
当cnt>2时,那么需要交换的次数是大于1的,故无法满足要求;
这题自己手太弱了,赛时一直调不出来,赛后重写了一遍才过。
注意:数组大小2e5,数组存会爆,可以采用vector存。
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
vector<int> v[maxn],vv[maxn];
int n,m;
int check(int i,int j)
{
for(int k=0;k<n;k++)
{
if(v[k][i]!=vv[k][j]||v[k][j]!=vv[k][i]) return 0;
}
return 1;
}
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
v[i].clear();
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
int x;
cin>>x;
v[i].pb(x);
}
vv[i]=v[i];
sort(vv[i].begin(),vv[i].end());
}
int ansi=-1,ansj=-1;
int f=1;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(v[i][j]!=vv[i][j])
{
if(ansi==-1||ansi==j)
{
ansi=j;
}
else if(ansj==-1||ansj==j)
{
ansj=j;
}
else f=0;
}
}
}
if(!f) cout<<"-1"<<endl;
else {
if(ansi==-1&&ansj==-1) cout<<"1 1"<<endl;
else if(check(ansi,ansj)) cout<<ansi+1<<" "<<ansj+1<<endl;
else cout<<"-1"<<endl;
}
}
return 0;
}
D. Traps
分析
需要经过n个陷阱,每个陷阱的伤害是a[i],有k次跳过陷阱的机会,但是一旦跳过一个陷阱之后,这个陷阱之后的每一个陷阱的伤害+1,求通过n个陷阱受到的最小伤害值。
先记录每个陷阱被跳过对总值的影响(不考虑跳过陷阱之间的影响)a[i]-(n-i)。再考虑跳过陷阱之后对其他陷阱的伤害值的影响,跳过m个陷阱,会使伤害减少m(因为跳过一个会让之后的陷阱伤害+1,并且我计算影响时计算了这个值,这个时候跳过,需要减去这个值)。
计算出每个独立跳过的伤害值,并从大到小跳过陷阱,再比较这个值与跳过陷阱个数,考虑继不继续跳过陷阱,一旦这个值小于,即不跳过任何陷阱,即此时伤害最小。
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=2e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
ll a[maxn];
bool cmp(ll a,ll b)
{
return a>b;
}
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
ll sum=0;
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
a[i]=a[i]-(n-i);
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=k;i++)
{
if(a[i]>-i)
{
sum-=a[i]+i-1;
}
else break;
}
cout<<sum<<endl;
}
return 0;
}
E. MEX vs DIFF
分析
一个数组a,经过最多k次将a[i]换为任意的非负整数,求最小的DIFF-MEX值。
DIFF:数组中不同数的个数。
MEX:数组中没有出现的最小的数。
为使最后差值最小,考虑使MEX值最大,令大于mex的不同数的个数尽量小:muitiset维护一下,让大于mex的数中,数量较少的数优先进行改变操作。
附上本题参考的题解
代码
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define guanliu ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const ll maxn=1e5+10;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double pi=acos(-1);
int a[maxn];
int n,k;
map<int,int> mp,dmp;
int main()
{
guanliu;
int t;
cin>>t;
while(t--)
{
mp.clear();
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
mp[a[i]]++;
}
dmp=mp;
sort(a+1,a+1+n);
int mex=0;
while(mp[mex])
{
mex++;
}
for(int i=n,j=k;i&&j;i--,j--)
{
if(a[i]<mex) break;
mp[mex]=1;
mp[a[i]]--;
while(mp[mex])
{
mex++;
}
}
multiset<int> s;
for(auto i : dmp)
{
if(i.first>mex)
{
s.insert(i.second);
}
}
int dif=mex;
for(auto i : s)
{
if(k>=i) k-=i;
else dif++;
}
cout<<dif-mex<<endl;
}
return 0;
}