1. 程式人生 > >2018年EC Final 校內選拔賽【解題報告】

2018年EC Final 校內選拔賽【解題報告】

問題 A: C基礎-求同存異

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 1  解決: 1
[提交][狀態][討論版][命題人:外部匯入][Edit] [TestData]

題目描述

輸入兩個陣列(陣列元素個數6和8),輸出在兩個陣列中都出現的元素(如a[6]={234567}b[8]={357911131519}則輸出3、5、7)。

輸入

第一行輸入a陣列,第二行輸入b陣列

輸出

輸出在兩個陣列中都出現的元素

樣例輸入

2 3 4 5 6 7
3 5 7 9 11 13 15 19

樣例輸出

3
5
7
import java.util.*;
import java.math.*;

public class Main{
	static int maxn=(int)(5e4+10);
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		LinkedList<Integer> a=new LinkedList<Integer>();
		ArrayList b=new ArrayList<Integer>();
		
		String A=cin.nextLine();
		int lenA=A.length();
		int num=0;
		for(int i=0;i<lenA;i++) {
			while(i<lenA) {
				num*=10;
				num+=(A.charAt(i)-'0');
				i++;
				if(i<lenA&&A.charAt(i)==' ') {
					a.add(num);
					num=0;
					break;
				}
			}
		}
		a.add(num);
		
		String B=cin.nextLine();
		int lenB=B.length();
		num=0;
		for(int i=0;i<lenB;i++) {
			while(i<lenB) {
				num*=10;
				num+=(B.charAt(i)-'0');
				i++;
				if(i<lenB&&B.charAt(i)==' ') {
					b.add(num);
					num=0;
					break;
				}
			}
		}
		b.add(num);

		ArrayList<Integer> ans=new ArrayList<Integer>();
		for(int i=0;i<a.size();i++) {
			boolean flag=false;
			for(int j=0;j<b.size();j++) {
				if(a.get(i)==b.get(j)) {
					ans.add(a.get(i));
					break;
				}
			}
		}
		
		for(int i=0;i<ans.size();i++) {
			System.out.println(ans.get(i));
		}
		cin.close();
	}
}

問題 B: C基礎-對角線和

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 2  解決: 2
[提交][狀態][討論版][命題人:外部匯入][Edit] [TestData]

題目描述

求一個3×3矩陣對角線元素之和。

樣例輸入

1 2 3
4 5 6
7 8 9

樣例輸出

15
import java.util.*;
import java.math.*;

public class Main{
	static int maxn=(int)(5e4+10);
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		int ans=0;
		for(int i=1;i<=3;i++)
			for(int j=1;j<=3;j++) {
				int x=cin.nextInt();
				if(i==j)	ans+=x;
			}
		System.out.println(ans);		
		cin.close();
	}
}

問題 C: C基礎-區域性求合

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 9  解決: 4
[提交][狀態][討論版][命題人:外部匯入][Edit] [TestData]

題目描述

輸入20個整數,輸出其中能被陣列中其它元素整除的那些陣列元素。

樣例輸入

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

樣例輸出

4
6
8
9
10
12
14
15
16
18
20
21
import java.util.*;
import java.math.*;

public class Main{
	static int maxn=(int)(5e4+10);
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
	
		ArrayList<Integer> a=new ArrayList<Integer>();
		ArrayList<Integer> ans=new ArrayList<Integer>();
		for(int i=0;i<20;i++) {
			int x=cin.nextInt();
			a.add(x);
		}
		//a.sort(null);
		for(int i=0;i<20;i++) {
			for(int j=0;j<20;j++) {
				if(i!=j&&a.get(i)%a.get(j)==0) {
					ans.add(a.get(i));
					break;
				}
			}
		}
		for(int i=0;i<ans.size();i++)
			System.out.println(ans.get(i));
		cin.close();
	}
}

 

問題 D: 楊輝三角

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 1  解決: 1
[提交][狀態][討論版][命題人:外部匯入][Edit] [TestData]

題目描述

還記得中學時候學過的楊輝三角嗎?具體的定義這裡不再描述,你可以參考以下的圖形: 

1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1

輸入

輸入資料包含多個測試例項,每個測試例項的輸入只包含一個正整數n(1<=n<=30),表示將要輸出的楊輝三角的層數

輸出

對應於每一個輸入,請輸出相應層數的楊輝三角,每一層的整數之間用一個空格隔開,每一個楊輝三角後面加一個空行。

樣例輸入

2 3

樣例輸出

1
1 1

1
1 1
1 2 1
import java.util.*;
import java.math.*;

public class Main{
	static int maxn=(int)(5e4+10);
	static long[][] f=new long[32][32];
	static void init() {
		f[1][1]=1;
		for(int i=2;i<=30;i++) {
			for(int j=1;j<=i;j++) {
				f[i][j]=f[i-1][j-1]+f[i-1][j];
			}
		}
	}
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		init();
		int ca=1;
		while(cin.hasNext()) {
			int n=cin.nextInt();
			if(ca!=1)
				System.out.println();
			ca++;
			for(int i=1;i<=n;i++) {
				for(int j=1;j<=i;j++) {
					System.out.print(f[i][j]);
					if(i==j)
						System.out.println();
					else
						System.out.print(" ");
				}
			}
		}
		cin.close();
	}
}

問題 E: Amon 愛遊戲

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 1  解決: 1
[提交][狀態][討論版][命題人:winsoul][Edit] [TestData]

題目描述

Amon 非常喜歡和 Congcong 玩遊戲。

現在有一堆含有 n 個石頭的石頭堆。

遊戲規則如下:

        1. Amon先手。

        2. 兩人輪流取石頭,每次可以從石堆取出 1 ~ 3 個石頭。

        3. 第一個沒有石頭取的同學輸掉比賽。

Amon 很好奇,如果他們都用最優策略來玩這個遊戲,誰可以獲勝。

輸入

輸入包含多組測試資料。

對於每組測試樣例,輸入一個正整數 n,表示石堆有 n 個石頭。(0 ≤ n ≤ 100000)。

輸出

對於每組測試輸出一行。

如果 Amon 贏得遊戲,輸出“Amon!!!”。

否則輸出“Congcong!!!”。

樣例輸入

1
2
3
4

樣例輸出

Amon!!!
Amon!!!
Amon!!!
Congcong!!!

四種博弈

巴什博弈:有N個物品,每次可以取1~M個,最後取完者勝。

假設N=M+1,那麼無論先手取多少個,後者一次便可取完,先手必敗

假設N=(M+1)* R+S(R為任意自然數,S<=M),那麼先手拿走S個物品,後手拿走K個物品(K<=M),先手拿走M+1-K個物品,剩餘(M+1)*(R-1)個物品,保持這樣的取法,先手必勝。

勝利法則:若N%(M+1)不等於0,先手必勝

import java.util.*;
import java.math.*;

public class Main{
	static int maxn=(int)(5e4+10);
	
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		int ca=1;
		while(cin.hasNext()) {
			int n=cin.nextInt();
			if(n%4!=0)
				System.out.println("Amon!!!");
			else
				System.out.println("Congcong!!!");
		}
		cin.close();
	}
}

問題 F: 有趣的體能測試

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 2  解決: 2
[提交][狀態][討論版][命題人:201606060136][Edit] [TestData]

題目描述

“蒼天啊!為什麼我一年比一年跑的慢,而體側及格線一年比一年高?”尤其是1000M,每次跑到懷疑人生!

為此,今年體育部出提出了一種新的體測專案:學生從出發點開始跑,必須經過兩個感測器,而且只能沿著南北方向和東西方向跑。

聰明的ACM選手,你知道怎樣跑最省力氣嗎?

輸入

本題包含多組測試,請處理到檔案結束。

每組測試樣例,第一行為四個整數,[x1,y1],[x2,y2],代表要經過的兩個感測器的座標。

為了簡化問題,出發點設為[0,0].

輸出

對於每組測試,輸出一個整數,代表最短距離

樣例輸入

1  1  2  2

樣例輸出

4

提示

所有運算元在32bit整型數範圍內

分析:

曼哈頓距離(或計程車距離)是1種使用在幾何度量空間的幾何學用語,用以標明兩個點在標準座標系上的絕對軸距總和。

圖中紅線代表曼哈頓距離,綠色代表歐氏距離,也就是直線距離,而藍色和黃色代表等價的曼哈頓距離。

曼哈頓距離——兩點在南北方向上的距離,加上在東西方向上的距離

例如在平面上,座標(x1, y1)的i點與座標(x2, y2)的j點的曼哈頓距離為:

d(i,j)=|X1-X2|+|Y1-Y2|.

既然必須經過兩個點,那麼只有兩種可能【原點->1號點->2號點】或者【原點->2號點->1號點】

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>

using namespace std;
const double eps = 1e-8;
const int maxn=2e5+10;

int main()
{
    int x1,y1,x2,y2;
    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    int ans1=abs(x1)+abs(y1)+abs(x2-x1)+abs(y2-y1);
    int ans2=abs(x2)+abs(y2)+abs(x1-x2)+abs(y1-y2);
    printf("%d\n",min(ans1,ans2));
}

問題 G: 圖書管理

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 22  解決: 6
[提交][狀態][討論版][命題人:201606060136]

題目描述

小虎參加陝西科技大學青年志願者服務團,經常去做志願活動,其中一項就是在圖書館幫忙整理書籍。
小虎的工作很簡單,就是把圖書分類放到書架上。比如,現在有一摞書【1,2,3】,(為了簡化問題,我們把書編號為1,2,3.....)
1號書在最上面,書架上需要把按【2,1,3】整理擺放。第一次小虎取2號書時,他會把【1,2】兩本書放到書架上;第二次需要1號書時,
1號書已經在書架上啦;第三次,他會把3號書放到書架上

輸入

第一行一個整數T,表示有T組資料。 
每組資料第一行一個正整數N(N<=2*10^5)表示有N本書
接下來有N個正整數,a1,a2,a3....an,代表一摞書,a1號書在最上面(1<=ai<=N)
接下來N個正數,b1,b2,b3....bn,代表N本書在書架上擺放的順序(1<=bi<=N)

輸出

對於每組測試樣例,輸出N個數,代表每次取書的數量。

樣例輸入

2
3
1 2 3
2 1 3
5
1 2 3 4 5
1 2 3 4 5 

樣例輸出

2 0 1
1 1 1 1 1

提示

對於第一個樣例,小虎一共取了三次書,第一次取2本,第二次取0本,第三次取1本,輸出【2  0  1】

分析:

根據題意,每次只能從一摞書的上面取走連續的K本書,那麼考慮使用一個棧來解決先進後出的問題,比如,現在有一摞書【1,2,3】,1號書在最上面,即棧頂元素;書架上需要把按【2,1,3】整理擺放。第一次小虎取2號書時,他會把【1,2】兩本書放到書架上,即先彈出1,然後彈出2;第二次需要1號書時,1號書已經在書架上啦;第三次,他會把3號書放到書架上,把彈出3;每次記錄一下出棧元素個數即可

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <math.h>
 
using namespace std;
const double eps = 1e-8;
const int maxn=2e5+10;
int a[maxn],b[maxn];
bool vis[maxn];
int ans[maxn];
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
 
    for(int j=1;j<=n;j++)
        scanf("%d",&b[j]);
    memset(ans,0,sizeof ans);
    memset(vis,0,sizeof vis);
    int top=1;
    for(int i=1;i<=n;i++){
        if(vis[b[i]]){
            ans[i]=0;
            continue;
        }
        int num=0;
        while(top<=n){
            int cur=a[top++];
            vis[cur]=1;
            num++;
            if(cur==b[i])
                break;
        }
        ans[i]=num;
    }
    for(int i=1;i<=n;i++)
        printf("%d%c",ans[i],i==n?'\n':' ');
    }
    return 0;
}

問題 H: 電音之王

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 3  解決: 1
[提交][狀態][討論版][命題人:201606060136][Edit] [TestData]

題目描述

終於活成了自己討厭的樣子。
聽說多聽電音能加快程式執行的速度。
小娜打了四年ACM,獲獎無數,畢業之後進入TX公司,成為一名演算法工程師。他所在的團隊負責應用程式的底層架構開發。
團隊中每個程式設計師都有幾個朋友,當然自己和自己不算朋友,因為擁有朋友,會獲得一定的快樂值。比如,現在團隊中有3個人,
如果一個程式設計師有1個朋友,那麼他的快樂值為2;如果一個程式設計師有2個朋友,那麼他的快樂值為1.團隊的快樂值就是團隊中
所有程式設計師的快樂值之和,團隊快樂值越大,工作效率越高。齊老闆想知道團隊快樂值最大是多少?

輸入

首先是一個整數T,代表有T組測試樣例。
對於每組測試樣例,第一行是一個數N,代表團隊中有N個人(N<=1000000)
第二行是N-1個數,a1,a2,a3,a4.......(<=100000000).,a1代表程式設計師有一個朋友時的快樂值,
a2代表程式設計師有兩個朋友時的快樂值,以此類推

輸出

對於每組測試樣例,輸出團隊最大的快樂值

樣例輸入

1
3
2 1

樣例輸出

5

分析:

團隊中有N個人,如果兩個是朋友,就建一條邊;顯然一個人最多N-1個朋友,自己和自己不算朋友(說明沒有自環),每個人至少一個朋友(說明圖是連通圖);

這樣n個點構成一棵樹,有n-1條邊,一共是2*n-2個度,而且確定的一點是每一個點都至少有1個度。這樣還剩下n-2個度。問題就轉化成了n-2個度分給n個點(每個點擁有的度數可以是0)。

但是題目給了n-1個f(i)意思就是說,有n-1種物品,每一種物品的種類都是無限的(因為每個點的度數是可以相同的),並且每件物品的價值都是v【i】=1,並且每件物品的體積(重量)都是i(就是這個物品的度數),然後把這n-1種物品,正好裝入一個容量為n-2的揹包裡

但是這道題還有個坑,就是我們默認了每個點都有了一個度了,所以實際上我們在列舉物品的時候,他們的度都是i+1(假設從1開始迴圈)

import java.math.*;
import java.util.*;
public class Main {
	static int maxn=2020;
	static int INF=(int)1e9;
	static int n,v;
	static int[] f=new int[maxn];
	static int[] dp=new int[maxn];
	
	static void DP() {
		for(int i=1;i<=n;i++)
			dp[i]=-INF;//求恰好裝滿揹包時的最優解,初始化為—INF
		dp[0]=0;//揹包容量為0,價值為0
		 v=n-2;//揹包容量

		 for(int i=1;i<=n-1;i++)//列舉物品
			 for(int j=i;j<=v;j++)//列舉揹包容量
				 dp[j]=Math.max(dp[j], dp[j-i]+f[i+1]-f[1]);//狀態轉移方程
	}
    public static void main (String[] args) {
    	 Scanner cin=new Scanner(System.in);
    	 int T=cin.nextInt();
    	 while((T--)!=0) {
    		 n=cin.nextInt();
    		 for(int i=1;i<=n-1;i++)
    			 f[i]=cin.nextInt();
    		 DP();
    		 System.out.println(dp[v]+f[1]*n);
    	 }
    	 cin.close();
      }
    }

問題 I: 模擬人生:大學生活

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 7  解決: 3
[提交][狀態][討論版][命題人:winsoul][Edit] [TestData]

題目描述

            如果不喜歡程式設計,學習演算法 和 學習高數有什麼不同?  —— 渣渣輝

小虎很喜歡《模擬人生:大學生活》這款遊戲,因為小虎可以在這款遊戲中控制虛擬角色做任何事情。

這款遊戲講述的是一個主人公在大學裡面的生活。

小虎非常喜歡演算法,當然在遊戲中也不例外。他說:“大學裡,只有演算法伴我左右。”。

於是他在遊戲中利用他的虛擬角色在學校學習了各種各樣的演算法,併發明瞭 KHP 演算法登上了 Time'  封面。

KHP 演算法是這樣描述的:

            1. 給定一個長度為 n 的非負整數序列 a ,和長度同為 n 的序列 b。( 0 <= ai <= 109,1 <= bi <= n)

            2. 你可以找出符合條件的 an+1,an+2,...,a2n,使得  最大。

找出 an,an+1,...,a2n 的方法如下:

            1. 對於每一個 ai ,你需要在 b 序列中選擇一個 bk ( b 中每個元素最多隻能選一次)。

            2.  ai = max{ aj - j | bk ≤ j < i}。

請你計算出

輸入

輸入包含多組測試資料。

對於每組測試資料:

第一行輸入為正整數 n,表示序列 a、b 的長度。(1 ≤ n ≤ 2*105)

第二行輸入為 n 個非負整數,為序列 a 的元素。

第三行輸入為 n 個正整數,為序列 b 的元素。

mod: 1000000007

輸出

對於每組測試資料,輸出的結果,佔一行。

樣例輸入

4
8 11 8 5
3 1 4 2

樣例輸出

59
#include <bits/stdc++.h>
using namespace std;
const int maxn = 400010;
const int mod = 1000000007;
long long int a[maxn], b[maxn], segtree[maxn << 4];

void build_tree(int l, int r, int now) {
  if (l == r) {
    segtree[now] = a[l] - l;
    return;
  }
  int mid = l + (r - l)/2;
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  segtree[now] = max(segtree[now << 1], segtree[(now << 1)|1]);
}

long long int query(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    return segtree[now];
  }
  long long int ans = 0;
  int mid = l + (r - l)/2;
  if (L <= mid) ans = max(ans, query(L, R, l, mid, now << 1));
  if (R > mid) ans = max(ans, query(L, R, mid + 1, r, (now << 1)|1));
  return ans;
}

void update(int l, int r, int tar, int c, int now) {
  if (l == r) {
    segtree[now] = c;
    return;
  }
  int mid = l + (r - l)/2;
  if (tar <= mid) update(l, mid, tar, c, now << 1);
  else update(mid + 1, r, tar, c, (now << 1)|1);
  segtree[now] = max(segtree[now << 1], segtree[(now << 1)|1]);
}

int main()
{
  int n;
  while (scanf("%d", &n) != EOF) {
    memset(segtree, 0, sizeof segtree);
    memset(a, 0, sizeof a);
    memset(b, 0, sizeof b);
    long long int ans = 0;
    for (int i = 1; i <= n; i++) {
      scanf("%lld", &a[i]);
      ans += a[i]%mod;
    }
    for (int i = 1; i <= n; i++) {
      scanf("%lld", &b[i]);
    }

    sort(b + 1, b + n + 1);
    build_tree(1, 2*n, 1);

    for (int i = 1; i <= n; i++) {
      long long int ai = query(b[i], n + i - 1, 1, 2*n, 1);
      ans += ai%mod;
      update(1, 2*n, n + i, ai - n - i, 1);
    }
    printf("%lld\n", ans%mod);
  }

  return 0;
}