A题
注意到所求函数f(f(x))实际上所作操作是去掉原数末尾的0,原数末尾如果无0,则值为1,否则有多少0就有多少种情况,所以,只需求得原数有多少位即可。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int main(){
string s;
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>s;
cout<<s.length()<<endl;
}
return 0;
}
B题
题意是说从零开始,第k次可以进行两种操作,把当前数字+k或者当前数字-1,问至少要经过多少次操作能够到达给定的目标数。
抽象出来就是说1+2+3+····+n=?x,对等号左面这n个数进行修改,改变其中若干个成为-1,使得等号成立,显然如果一个x,恰好有一个n能使等号成立,那么最小操作数就是n;对于普通的情况,只需要把-1放在1或者放在n的位置上就能判断出x的取值范围,在这样一个范围中,n是最小操作数,这样分类讨论可以得到结果,此题数据范围不大。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
bool judge(int x){
int t=sqrt(2*x);
if(t*(t+1)==2*x) return true;
return false;
}
int main(){
int n,m;
cin>>n;
for(int i=0;i<n;i++){
cin>>m;
if(judge(m)) cout<<(int)sqrt(2*m)<<endl;
else{
for(int j=1;;j++){
if((j-2)*(j+1)/2<=m&&(j*(j+1)/2-2>=m)) {
cout<<j<<endl;
break;
}
}
}
}
return 0;
}
在网上发现了一个更科学的解法:
考虑n是满足1+2+⋯+n≥x的最小n,记s=1+2+⋯+n.
有三种情况:
i.s=x,答案显然为n.
ii.x+1<s<x+n,那么可以通过替换第k个数为−1,使得s−k−1=x,答案为n.
iii.s=x+1,那么无论替换哪个数都不能使得s−k−1=x,需要额外的一步−1,因此答案为n+1.
膜拜,附上链接
红名大佬
如下
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
int get_n(int x){
int sum=0;
for(int i=1;;i++){
sum+=i;
if(sum>=x) return i;
}
return 0;
}
int main(){
int t,x;
cin>>t;
while(t--){
cin>>x;
int n=get_n(x);
int sum=(1+n)*n/2;
if(sum==x){
cout<<n<<endl;
}else if(sum>x+1&&sum<x+n) cout<<n<<endl;
else if(sum==x+1)cout<<n+1<<endl;
}
return 0;
}
C题
讲的是alice和bob打球,触球则扣一点体力值,问两者能赢的局数的最大值分别为多少。
alice发球,bob如果想让他赢得次数多一些,他就一直不能接,直到alice就剩一点体力,他接球得分,紧接着就是他一直发球一直得分,所以bob最多得分为y,在这种情况下alice赢得次数显然是x-1
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int main(){
int t,x,y;
cin>>t;
while(t--){
int alice,bob;
alice=bob=0;
cin>>x>>y;
cout<<x-1<<' '<<y<<endl;
}
return 0;
}
D题
给定一个x和一个数组,将x与数组中任意一个元素交换位置,问最少多少次能使得数组从小到大排序。
如果数组本来就有序显然不需要再排,所以检测数组中第一个无序的地方,发现了以后要从数组头开始看,看x是不是比它小,如果比它小就要一个一个得换,否则就往后看,直到到达现在的位置。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAX=1e5+10;
int Data[MAX];
int main(){
int t,n,x;
cin>>t;
while(t--){
cin>>n>>x;
int ans=0;
bool flag=true;
for(int i=0;i<n;i++) {
cin>>Data[i];
if(i>=1){
if(Data[i-1]>Data[i]){
for(int j=0;j<=i;j++){
if(Data[j]>x) {
swap(Data[j],x);
ans++;
}
}
}
}
}
for(int i=1;i<n;i++){
if(Data[i-1]>Data[i]){
flag=false;
break;
}
}if(!flag) cout<<-1<<endl;
else cout<<ans<<endl;
}
return 0;
}