1. 程式人生 > 其它 >大一限時訓練題解

大一限時訓練題解

A - Happy New Year!

        

官方題解:

Let’s enumerate the integers that satisfy the condition.

      2
     20
     22
    200
    202
    220
    222
   2000
   2002
   2020
   2022
    ...

(其實就是把十進位制換成二進位制...............)這題我看你們正確率挺高的,差不多隻要你們提交了程式碼(看出了二進位制),結果基本上都是對的。

#include <iostream>
using namespace std;
int ans[64];
int main()
{
    long long int t;
    cin>>t;
    int flag=0;
    while(t){
        if(t&1){
            ans[flag++]=2;
        }
        else{
            ans[flag++]=0;
        }
        t=t>>1;
    }
    for(int i=flag-1;i>=0;i--){//別忘了,要倒序輸出來答案
        cout<<ans[i];
    }
    cout<<endl;
    return 0;
}

  

B - 抱抱熊的RGB氣球

      

給你一個字串,怎麼樣才能儘可能少地更換其中一些字元使這個字串相鄰的字串沒有相同的,輸出最少的更換次數。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--){
        string s;
        cin>>s;
        int flag=0,sum=0;//sum統計的是更換次數
        for(int i=0;i<s.length();i++){
            if(i==0){
                flag=1;
            }
            else{
                if(s[i]==s[i-1]){
                    flag++;
                }
                else{
                    sum+=flag/2;
                    flag=1;
                }
            }
        }
        sum+=flag/2;//別忘了,最後那一串互相相鄰且相同的子串還沒有考慮
        cout<<sum<<endl;
    }
    return 0;
}

  

C - 排列的最大值和

      

這題,對於你們來說應該挺難的,但是沒有一個人做出來,這很不應該,列一個有序a序列,然後交換次序,觀察sum的值,你們應該能做出來。

然後寫兩個“指標”(此指標非彼指標),通過指標移動,交換序列中的元素,得到b序列。

#include <iostream>
#include <cstdio>
using namespace std;
int ans[100005];//存放序列a
int num[100005];//存放1....n序列交換後的序列

int main()
{
    //std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    //cin>>t;
    scanf("%d",&t);
    while(t--){
        long long int n;//這裡要用long long定義n,否則n*(n+1)/2中途會爆掉
        long long int sum;
        //cin>>n>>sum;
        scanf("%lld%lld",&n,&sum);
        for(int i=1;i<=n;i++){
            //cin>>ans[i];
            scanf("%d",&ans[i]);
            num[i]=i;
        }
       
        long long int summin=n*(n+1)/2;//sum的最小可能的值
        long long int ext=sum-summin;//ext存放的是差值,後面的迴圈判斷要用到這個差值
        long long int flagi=1,flagj=n;//兩個指標
        while(ext){//當差值不為0的時候,進入迴圈
            if(ext<=flagj-flagi){//每次迴圈利用的ext是否小於等於允許的的最大差值
                swap(num[flagi],num[flagi+ext]);//如果小於等於,就交換應該交換的兩個num存的值
                ext=0;//這種情況滿足以後,就不用再進行迴圈了,所以要把ext置為0
            }
            else{
                swap(num[flagi],num[flagj]);//如果ext要大於每次迴圈允許的差值,就在移動兩端指標之前,交換兩端指標所在位置num所存的值
                ext-=flagj-flagi;  //同時更新差值
                flagi++;
                flagj--;
            }
        }
        for(int i=1;i<=n;i++){
            if(i==1){
                //cout<<ans[num[i]];
                printf("%d",num[ans[i]]);
            }
            else{
                //cout<<" "<<ans[num[i]];
                printf(" %d",num[ans[i]]);
            }
        }
        //cout<<endl;
        printf("\n");
    }
    return 0;
}
 
稍微改變了一下輸入輸出方式(少定義一個數組):
 
#include <iostream>
#include <cstdio>

using namespace std;
long long int ans[100005];
long long fun(long long n)
{
    return n*(n+1)/2;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        long long int sum;
        scanf("%d%lld",&n,&sum);
        for(int i=1;i<=n;i++){
            ans[i]=i;
        }
        long long int mi=fun(n);
        long long int ext=sum-mi;
        long long int flagj=n;
        long long int flagi=1;
        while(ext){
            if(ext<=flagj-flagi){
                swap(ans[flagi],ans[flagi+ext]);
                ext=0;
            }
            else{
                swap(ans[flagi],ans[flagj]);
                ext-=flagj-flagi;
                flagi++;
                flagj--;
            }
        }
        int h;
        for(int j=1;j<=n;j++){
            scanf("%d",&h);
            if(j==1){
                printf("%d",ans[h]);
            }
            else{
                printf(" %d",ans[h]);
            }
        }
        printf("\n");
    }
    return 0;
}