1. 程式人生 > >北京化工大學2018年10月程式設計競賽部分題解(A,C,E,H)

北京化工大學2018年10月程式設計競賽部分題解(A,C,E,H)

目錄

北京化工大學2018年10月程式設計競賽部分題解(A,C,E,H)

競賽事件相關

競賽連結

雖然我發這個隨筆的時候估計已經比完了,不過還是把連結放上來好了。

一個比賽

http://116.196.97.99/contest.php如果連結沒設定好的話,可以在這裡複製網址

競賽題目

我做出來的

C.水題的ZZH
題目描述

ZZH是北化acm界新生代的大佬,每天會和無數來自全球各地的大佬進行交流。但是,ZZH每天水群的時間有限。ZZH想盡可能多的和更強的大佬進行交流。他把每個大佬的實力用一個數字Ω表示出來,並且每天和Ω總和最高的幾位大佬進行交流。但是ZZH正在忙著水群,於是把這個問題交給了你。事成之後,ZZH會給你2147483647%1的金幣作為獎勵

輸入

單組資料

第一行兩個整數n,m,分別代表今天ZZH水群的時間(以分計算)和今天想要與ZZH交流的大佬的數量(<=2000)。

之後m行,分別有兩個數字,代表和第i個大佬交流花費的時間(<n),以及大佬的Ω(<1000)。

輸出

今天與ZZH交流的大佬的Ω的值的總和。

樣例輸入
70 3
71 100
69 3
1 2
樣例輸出
5

這道題一看就是很常見的揹包問題,然後我不會做了,我用了自己以前的程式碼,我檢討,我反思!

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int V,n;
    cin>>V>>n;
    int v[2100],p[2100],dp[2100];
    memset(v,0,sizeof(v));
    memset(p,0,sizeof(p));
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)
        cin>>v[i]>>p[i];
    for(int i=1;i<=n;i++)
        for(int j=V;j>=v[i];j--)
            dp[j]=max(dp[j-v[i]]+p[i],dp[j]);
    cout<<dp[V];
}

揹包問題會就是會,不會也寫不出來,大概。沒什麼好說的,下一道吧。

A.智力大獎賽
題目描述

imgimg

輸入

只有一行,有一個整數N,表示大三角形的層數(N<=45000)

輸出

有兩行,
第一行只有一個數,表示小三角形的個數;
第二行也只有一個數,表示能量棒的個數。

樣例輸入
8
樣例輸出
64
108

聽坐我對面的說A很好做,但是資料太大了。

emmmmm,好的,沒問題,BigInteger走起!

大概思路就是第1行1個三角,第2行2+1個,第3行3+2個……

然後能量棒是第1行3根,第2行6根,第3行9根……

很簡單的一道題,難點就在資料太大,不過,我BigInteger怕過誰??

import java.math.BigDecimal;
import java.util.Scanner;
import java.math.BigInteger;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();
        BigInteger x1 = BigInteger.ZERO;
        BigInteger x2 = BigInteger.ZERO;
        BigInteger x3 = BigInteger.ZERO;
        BigInteger y1 = BigInteger.ZERO;
        BigInteger a1 = BigInteger.ONE;
        BigInteger b1 = BigInteger.ONE;
        BigInteger a2 = BigInteger.ZERO;
        b1=b1.add(a1);
        b1=b1.add(a1);
        for(int i=0;i<n;i++) {
            x1=x1.add(a1);
            x2=x2.add(a2);
            a1=a1.add(BigInteger.ONE);
            a2=a2.add(BigInteger.ONE);
            y1=y1.add(b1);
            b1=b1.add(BigInteger.ONE);
            b1=b1.add(BigInteger.ONE);
            b1=b1.add(BigInteger.ONE);
        }
        x3=x1.add(x2);
        System.out.println(x3); 
        System.out.println(y1); 
    }

}

能隨意切換C++和JAVA的我真棒233333

下一道,H吧,感覺挺簡單的啊

H.數列
題目描述

故事不編了,m哥牛逼!

給出一個長度為n的數列a,現在有如下三種操作:
1、 1 p x: 將a[p]更改為x
2、 2 l r: 求a[l]到a[r]的最大值與最小值的差
3、 3 l r: 求a[l]到a[r]的和
現在給你一些操作,請你求出相應的數值。

輸入

第一行輸入一個數字T表示資料組數(1<=T<=10)
接下來T組資料,每組資料第一行為兩個整數n、m(1<=n,m<=1e5),分別代表a的長度和運算元,下一行n個整數表示a[1]到an,接下來m行,每行一個如題目給出的輸入格式的操作
(1<=p,l,r<=n,0<=x<=1000)

輸出

對於每組資料
對每一個操作2或3,輸出一個整數表示結果

樣例輸入
2
4 4
1 2 3 4
2 1 2
1 2 7
2 1 2
3 1 4
5 4
2 7 6 3 8
2 1 3
1 3 1
2 1 5
3 3 3
樣例輸出
1
6
15
5
7
1

這題真的很簡單啊,不就是一些陣列的操作嗎?怎麼做的人那麼少。。。

唯一需要注意的就是題目中的陣列是從1開始的。

#include <iostream>
using namespace std;
int suan(int a[],int l,int r){
    int m1,m2;
    m1=a[l];
    m2=a[l];
    for(int i=l+1;i<=r;i++){
        m1=m1>a[i]?m1:a[i];
        m2=m2<a[i]?m2:a[i];
    }
    return m1-m2;
}
int add(int a[],int l,int r){
    int s=0;
    for(int i=l;i<=r;i++){
        s+=a[i];
    }
    return s;
}
int main()
{
    int t,n,m,x,p,y,l,r;
    cin>>t;
    while(t--){
        cin>>n>>m;
        int a[n+1];
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        while(m--){
            cin>>x;
            switch(x){
                case 1:cin>>p>>y;
                        a[p]=y;
                        break;
                case 2:cin>>l>>r;
                        cout<<suan(a,l,r)<<endl;
                        break;
                case 3:cin>>l>>r;
                        cout<<add(a,l,r)<<endl;
                        break;
            }
        }
    }
}

請不要在意我亂起的函式名!

然後這個時候我發現我排第12??!從來沒這麼高過,信心大增!!!

繼續加油!

看E好像做的人挺多的,我也來試試吧!

E.雲端計算
題目描述

北化ACM社團有n臺雲伺服器,每臺伺服器都有一個使用期限,第i臺伺服器還能使用Ri天。現在有m個任務需要部署到雲伺服器上執行,第j個任務需要執行Tj天。第j個任務能夠部署在第i臺伺服器上時當且僅當 Tj <=Ri,並且每臺伺服器在其使用期限內總共只能執行一個任務。即使Tk+Tj <=Ri,你也無法將第k個和第j個任務一起部署到第i 臺伺服器上,否則這題將失去其簽到題的作用(看到簽到題這幾個字的時候我笑了)。為了能充分利用雲伺服器,現在需要計算最多能部署多少任務。而你作為北化ACM的希望,這個問題需要由你 來解決。

輸入

單組資料
第一行兩個整數代表 n和m
第二行 n個整數代表 R1,R2,...,Rn
第三行 m個整數代表T1,T2,...,Tm
1<= n,m,Tj ,Ri <=100000

輸出

輸出一個整數代表最多有多少個任務能夠部署到雲伺服器上

樣例輸入
5 5
6 1 3 4 2 
4 6 6 2 5 
樣例輸出
3

既然是簽到題,哈哈,那就沒什麼好說的了,來吧,我不怕你!

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int n,m,s=0;
    cin>>n>>m;
    int a[n],b[m];
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i=0;i<m;i++){
        cin>>b[i];
    }
    sort(a,a+n);
    sort(b,b+n);
    int j=0;
    for(int i=0;i<m;){
        if(b[i]<=a[j]){
            i++;
            j++;
            s++;
        }
        else{
            j++;
        }
        if(j==n){
            break;
        }
    }
    cout<<s;
}

嗯,很簡單,就隨便排排序,然後判斷一下使用期限夠不夠就行了。

然後!!!第8了!!!

不過很可惜,我就止步4道了,之後再也沒做出來了,名次也掉到了50多名,不過也很強了啊!好久不做題了竟然還能突破之前的最後成績。

我沒做出來的

B.求素數
題目描述

img

輸入

共兩行:
第一行為N何L,中間用空格隔開。 (1<=N<=100 , 1<=L<=7)
第二行為N個0~9的數字,中間用空格隔開。

輸出

只有一行,含全部滿足條件的素數,中間用逗號隔開,保證至少存在一個素數。

樣例輸入
10 3
8 9 1 0 2 3 5 4 7 6
樣例輸出
547

自己感覺程式碼沒問題了,但就是過不了。。就不放了。

D.積木
題目描述

我懶得編故事了 m哥牛逼!
有n個積木,第i個積木的高度為a[i],求每個積木前面有幾個比它矮的積木

輸入

多組輸入,每組由兩行組成,第一行輸入n,第二行輸入n個數,為n個積木的高度a[i]
//(1<=n<=100000)(1<=a[i]<=1000000000)

輸出

每組資料輸出n個數,第i個數為第i個積木前面比他矮的積木的個數

樣例輸入
5
1 2 3 4 5
樣例輸出
0 1 2 3 4

這道題是喜聞樂見的超時,最後也沒找到好的演算法。

看不懂,不想看的

F.羅dalao的密碼
題目描述

眾所周知,羅dalao十分的厲害。有一天,羅dalao發明了一種密碼,用來給文件加密(可認為文件是一個長度為n的字串s)。
羅dalao要對s[l]...s[r]加密,首先要反轉區間s[l]...sr,然後使k=(r-l+1)/2(向下取整),再反轉區間s[l]...s[l+k-1]和s[l+k]...s[r],以此類推,一直到區間長度都為1為止。(加密整個文件相當於加密區間s[1]...s[n])
有一天你找到了一篇羅dalao加密過的文件,現在要你求出某個位置的字元加密前的位置。

輸入

第一行輸入整數T(0<T<=1000),表示資料組數,接下來T行,每行兩個整數n和p(1<=p<=n<=1e18),分別表示文件長度和詢問的位置

輸出

輸出T行,每行一個整數,表示每組資料中加密後p位置的字元的原位置

樣例輸入
4
4 1
4 2
4 3
4 4
樣例輸出
3
4
1
2
G.羅dalao的小電影
題目描述

羅dalao非常的厲害,於是會有很多人向他請教一些問題,而他每天有L分鐘專門用來解答問題。由於來請教的人很多,所以要找羅dalao請教問題,需要預定。
於是,羅dalao知道每天會有n個人來請教問題,第i個到來的人在第ai分鐘到來,羅dalao解答問題要用ti分鐘(羅dalao精明的安排保證ai+ti<=ti+1和an+tn<=L),然而羅dalao想找空閒的時間看小電影,羅dalao看每一部小電影都要從頭看到尾,期間不能有中斷,每部小電影的時長為m,羅dalao想知道他每天最多可以看多少部小電影,現在請你幫他計算一下。

輸入

單組
第一行3個整數:n,L和m(0<=n<=1e5,1<=L<=1e9,1<=m<=L)
接下來n行,每行兩個整數ai和ti(0<=ai<=L-1,1<=ti<=L)

輸出

輸出一個整數,表示羅dalao最多能觀看多少部小電影

樣例輸入
2 11 3
0 1
1 1
樣例輸出
3
I.Leo的簡單規律題
題目描述

Leo喜歡吃燒烤,而且只吃三種,羊肉串,青菜,火腿腸,她吃燒烤之前喜歡把燒烤擺成一長串,而且還有特別的擺放規則,擺錯了她這一頓就不吃了。
規則有:1.對於連續的三個烤串,不能三個烤串都是同一種。
2.對於連續的三個烤串,如果三種烤串都有,青菜不能放在中間(在吃肉中途吃菜是會令人自閉的)
3.依舊是對於連續的三個烤串,第一串和第三串都是青菜的話,中間不能是羊肉或者火腿腸(她的意思是吃素減肥)
現在有三種烤串都有無數根,她想擺出長度為n的烤串,請你求出方案數(由於結果可能會很大,所以只需給出答案模1000000007)

輸入

第一行有一個數字T(T<100),表示有T組資料
接下來的T行,每行一個數字n (1≤N≤1010)

輸出

對於每一組資料,輸出擺出長度為n的烤串的方案數

樣例輸入
4
2
3
4
6
樣例輸出
9
20
46
244
問題 J.Leo的簡單數列
題目描述

Leo有兩個數列,它們的長度都是n
在最開始,a數列裡都是0,b數列是Leo隨機填充的n個數(數字為1-n,保證b數列是1-n的一個排列)
現在Leo可以進行兩種操作
\1. add L R 表示她給a數列從a[L],a[L+1],...,a[R],都加一

  1. query L R 表示她想知道當 L<= i <=R 時 a[i]/b[i](向下取整)的所有項的總和
    當然Leo在數學這一塊還不是很熟練,上次月考數學才110分,所以想請你幫她完成這些操作
輸入

多組資料
對於每組資料,第一行有2個數字n,q,表示a與b的長度 和運算元。1<= n,q < =100000
第二行有n個數字,表示數列b的初始狀態
接下來的q行,每行一個操作,具體操作格式如題目所給
1<= L <= R <= n

輸出

對於每一個query操作,輸出一行表示求和的結果。

樣例輸入
6 10
6 1 4 3 2 5
query 1 4
add 2 2
query 3 6
add 1 6
add 3 4
query 2 5
query 1 6
add 2 4
query 1 4
query 3 5
樣例輸出
0
0
2
2
4
1

總結

我果然還是隻能做簡單題。。

競賽網站