算法競賽進階指南0x08 總結練習(下)

數的進制轉換

編寫一個程序,可以實現將一個數字由一個進制轉換爲另一個進制。

這裏有62個不同數位{0-9,A-Z,a-z}。

輸入格式
第一行輸入一個整數,代表接下來的行數。

接下來每一行都包含三個數字,首先是輸入進制(十進制表示),然後是輸出進制(十進制表示),最後是用輸入進製表示的輸入數字,數字之間用空格隔開。

輸入進制和輸出進制都在2到62的範圍之內。

(在十進制下)A = 10,B = 11,…,Z = 35,a = 36,b = 37,…,z = 61 (0-9仍然表示0-9)。

輸出格式
對於每一組進制轉換,程序的輸出都由三行構成。

第一行包含兩個數字,首先是輸入進制(十進制表示),然後是用輸入進製表示的輸入數字。

第二行包含兩個數字,首先是輸出進制(十進制表示),然後是用輸出進製表示的輸入數字。

第三行爲空白行。

同一行內數字用空格隔開。

輸入樣例:
8
62 2 abcdefghiz
10 16 1234567890123456789012345678901234567890
16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 23 333YMHOUE8JPLT7OX6K9FYCQ8A
23 49 946B9AA02MI37E3D3MMJ4G7BL2F05
49 61 1VbDkSIMJL3JjRgAdlUfcaWj
61 5 dl9MDSWqwHjDnToKcsWE1S
5 10 42104444441001414401221302402201233340311104212022133030
輸出樣例:
62 abcdefghiz
2 11011100000100010111110010010110011111001001100011010010001

10 1234567890123456789012345678901234567890
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2

16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 333YMHOUE8JPLT7OX6K9FYCQ8A

35 333YMHOUE8JPLT7OX6K9FYCQ8A
23 946B9AA02MI37E3D3MMJ4G7BL2F05

23 946B9AA02MI37E3D3MMJ4G7BL2F05
49 1VbDkSIMJL3JjRgAdlUfcaWj

49 1VbDkSIMJL3JjRgAdlUfcaWj
61 dl9MDSWqwHjDnToKcsWE1S

61 dl9MDSWqwHjDnToKcsWE1S
5 42104444441001414401221302402201233340311104212022133030

5 42104444441001414401221302402201233340311104212022133030
10 1234567890123456789012345678901234567890

這是一道非常基礎的進制轉化題,A進制->B進制,但是要用高精度,一般思維是先A->10,然後10->B,但是這題的做法可以一步到位,A->B,回顧一下10->B進制,我們ans.push_back(a%B) a/=B,這是我們基於10進制的除法,那我們如果能實現a關於A進制的除法,我們是不是就能一步到位了呢?~ 。~,來看代碼。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>

using namespace std;

inline int get(char ch)
{
    if(ch>='A'&&ch<='Z') return ch-'A'+10;
    else if(ch>='a'&&ch<='z') return ch-'a'+36;
    return ch-'0';
}

inline char out(int num)
{
    if(num<=9&&num>=0) return num+'0';
    else if(num>=10&&num<=35) return num-10+'A';
    else return num-36+'a';
}

int main(){

    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);

    int T;
    cin>>T;

    while(T--)
    {
        int a1,a2;
        string s1,s2;
        cin>>a1>>a2>>s1;
        vector<int> v;
        for(auto ch:s1)
            v.push_back(get(ch));
        
        reverse(v.begin(),v.end());
        while(v.size())
        {
            int t=0;
            for(int i=v.size()-1;i>=0;i--)
            {
                t=a1*t+v[i];
                v[i]=t/a2;
                t%=a2;
            }
            s2.push_back(out(t));
            while(v.size()&&v.back()==0) v.pop_back();
        }
        reverse(s2.begin(),s2.end());
        cout<<a1<<" "<<s1<<endl<<a2<<" "<<s2<<endl;
        puts("");
    }

    return 0;
}

耍雜技的牛

農民約翰的N頭奶牛(編號爲1…N)計劃逃跑並加入馬戲團,爲此它們決定練習表演雜技。

奶牛們不是非常有創意,只提出了一個雜技表演:

疊羅漢,表演時,奶牛們站在彼此的身上,形成一個高高的垂直堆疊。

奶牛們正在試圖找到自己在這個堆疊中應該所處的位置順序。

這N頭奶牛中的每一頭都有着自己的重量Wi以及自己的強壯程度Si。

一頭牛支撐不住的可能性取決於它頭上所有牛的總重量(不包括它自己)減去它的身體強壯程度的值,現在稱該數值爲風險值,風險值越大,這隻牛撐不住的可能性越高。

您的任務是確定奶牛的排序,使得所有奶牛的風險值中的最大值儘可能的小。

輸入格式
第一行輸入整數N,表示奶牛數量。

接下來N行,每行輸入兩個整數,表示牛的重量和強壯程度,第i行表示第i頭牛的重量Wi以及它的強壯程度Si。

輸出格式
輸出一個整數,表示最大風險值的最小可能值。

數據範圍
1≤N≤50000,
1≤Wi≤10,000,
1≤Si≤1,000,000,000
輸入樣例:
3
10 3
2 5
3 3
輸出樣例:
2

和那個國王遊戲挺像的,我們按強壯+體重重的牛排個序就行了。

#include<iostream>
#include<cstring>
#include<algorithm>

#define ll long long
#define pll pair<ll,ll>

using namespace std;

const int N=50010;

pll cows[N];
int n;

bool CMP(const pll &a,const pll &b)
{
    return a.first+a.second<b.first+b.second;
}
int main(){
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    
    scanf("%d",&n);

    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&cows[i].first,&cows[i].second);
    
    sort(cows+1,cows+n+1,CMP);
    ll temp=0;
    ll res=-100000000000;

    for(int i=1;i<=n;i++)
    {
        res=max(res,temp-cows[i].second);
        temp+=cows[i].first;
    }

    printf("%lld\n",res);
    

    return 0;
}

最大的和

給定一個包含整數的二維矩陣,子矩形是位於整個陣列內的任何大小爲1 * 1或更大的連續子陣列。

矩形的總和是該矩形中所有元素的總和。

在這個問題中,具有最大和的子矩形被稱爲最大子矩形。

例如,下列數組:

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩形爲:

9 2
-4 1
-1 8
它擁有最大和15。

輸入格式
輸入中將包含一個N*N的整數數組。

第一行只輸入一個整數N,表示方形二維數組的大小。

從第二行開始,輸入由空格和換行符隔開的N2個整數,它們即爲二維數組中的N2個元素,輸入順序從二維數組的第一行開始向下逐行輸入,同一行數據從左向右逐個輸入。

數組中的數字會保持在[-127,127]的範圍內。

輸出格式
輸出一個整數,代表最大子矩形的總和。

數據範圍
1≤N≤100
輸入樣例:
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1

8 0 -2
輸出樣例:
15

這個題就是最長子序和的二維版本,一維用暴力,一維用DP就可以了hh,沒什麼好說的,來看代碼。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<limits.h>

using namespace std;

const int N=110;

int g[N][N];
int n;

int main(){
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);

    cin>>n;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>g[i][j];
            g[i][j]+=g[i-1][j];
        }
    
    int res=INT_MIN;

    for(int i=1;i<=n;i++)
        for(int j=0;j<i;j++)
        {
            int last=0;
            for(int k=1;k<=n;k++)
            {
                last=max(last,0)+g[i][k]-g[j][k];
                res=max(res,last);
            }
        }

    cout<<res<<endl;
    return 0;
}

任務

今天某公司有M個任務需要完成。

每個任務都有相應的難度級別和完成任務所需時間。

第i個任務的難度級別爲yi,完成任務所需時間爲xi分鐘。

如果公司完成此任務,他們將獲得(500 * xi + 2 * yi)美元收入。

該公司有N臺機器,每臺機器都有最長工作時間和級別。

如果任務所需時間超過機器的最長工作時間,則機器無法完成此任務。

如果任務難度級別超過機器的級別,則機器無法完成次任務。

每臺機器一天內只能完成一項任務。

每個任務只能由一臺機器完成。

請爲他們設計一個任務分配方案,使得該公司能夠最大化他們今天可以完成的任務數量。

如果有多種解決方案,他們希望選取賺取利潤最高的那種。

輸入格式
輸入包含幾個測試用例。

對於每個測試用例,第一行包含兩個整數N和M,分別代表機器數量和任務數量。

接下來N行,每行包含兩個整數xi,yi,分別代表機器最長工作時間和機器級別。

再接下來M行,每行包含兩個整數xi,yi,分別代表完成任務所需時間和任務難度級別。

輸出格式
對於每個測試用例,輸出兩個整數,代表公司今天可以完成的最大任務數以及他們將獲得的收入。

數據範圍
1≤N,M≤100000,
0<xi<1440,
0≤yi≤100
輸入樣例:
1 2
100 3
100 2
100 1
輸出樣例:
1 50004

貪心策略:按第一個爲第一關鍵字,第二個爲第二關鍵字排序,真的沒什麼好說的,和防曬那題很像,基操hh,因爲第二關鍵字根本無法改變局面,最多也只有100。~ 。~

#include<iostream>
#include<algorithm>
#include<cstring>
#include<set>

#define pii pair<int,int>
#define ll long long

using namespace std;

const int N=100010;

pii mach[N],task[N];
int n,m;

inline int calc(const pii &p)
{
    return 500*p.first+2*p.second; 
}

int main(){
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);

    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
            cin>>mach[i].first>>mach[i].second;
        for(int i=1;i<=m;i++)
            cin>>task[i].first>>task[i].second;
        sort(mach+1,mach+n+1);
        sort(task+1,task+m+1);
        multiset<int> s;
        ll res=0,cnt=0;
        for(int i=m,j=n;i>=1;i--)
        {
            while(j>=1&&task[i].first<=mach[j].first) s.insert(mach[j--].second);
            auto it=s.lower_bound(task[i].second);
            if(it!=s.end())
            {
                res+=calc(task[i]);
                s.erase(it);
                cnt++;
            }
        }
        cout<<cnt<<" "<<res<<endl;    
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章