codeforces round99 A-D

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;
}

猜你喜欢

转载自blog.csdn.net/roadtohacker/article/details/110440495