2018-第九屆藍橋杯大賽個人賽省賽(軟件類)真題 C大學A組


返回目錄

題目一覽:

1.分數

2.星期一

3.乘積尾零

4.第幾個幸運數

5.打印圖形

6.航班時間

7.三體攻擊

8.全球變暖

9.倍數問題

10.付賬問題

 

1.分數

1/1 + 1/2 + 1/4 + 1/8 + 1/16 + ....
每項是前一項的一半,如果一共有20項,
求這個和是多少,結果用分數表示出來。
類似:
3/2
當然,這只是加了前2項而已。分子分母要求互質。

注意:
需要提交的是已經約分過的分數,中間任何位置不能含有空格。
請不要填寫任何多余的文字或符號。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int gcd(int a, int b) {
 5     return b? gcd(b, a%b):a;
 6 }
 7 
 8 int main() {
 9     int c = 1 << 20;
10     int a = 0, b = 1;
11     for(int i=1; i<=20; ++i) {
12         a += c / b;
13         b *= 2;
14     }
15     c = gcd(a, b);
16     printf("%d/%d\n", a/c, b/c);
17     return 0;
18 }
1.分數

答案:1048575/524288

 

2.星期一

整個20世紀(1901年1月1日至2000年12月31日之間),一共有多少個星期一?
(不要告訴我你不知道今天是星期幾)

注意:需要提交的只是一個整數,不要填寫任何多余的內容或說明文字。

思路:首先要知道2000 12 31 星期日,然后求有多少天除以7,咱看看模7的余數就好。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 bool check(int x) {
 5     return ((x%4==0) && (x%100)!=0) || x%400==0;
 6 }
 7 
 8 int main() {
 9     int sum = 0;
10     for(int i=1901; i<=2000; ++i)
11         if(check(i)) sum += 366;
12         else sum += 365;
13     printf("%d\n", sum/7);
14     return 0;
15 }
2.星期一

答案:5217

 

3.乘積尾零

如下的10行數據,每行有10個整數,請你求出它們的乘積的末尾有多少個零?

5650 4542 3554 473 946 4114 3871 9073 90 4329 
2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 
9937 1173 6866 3397 4759 7557 3070 2287 1453 9899 
1486 5722 3135 1170 4014 5510 5120 729 2880 9019 
2049 698 4582 4346 4427 646 9742 7340 1230 7683 
5693 7015 6887 7381 4172 4341 2909 2027 7355 5649 
6701 6645 1671 5978 2704 9926 295 3125 3878 6785 
2066 4247 4800 1578 6652 4616 1113 6205 3264 2915 
3966 5291 2904 1285 2193 1428 2265 8730 9436 7074 
689 5510 8243 6114 337 4096 8199 7313 3685 211

注意:需要提交的是一個整數,表示末尾零的個數。不要填寫任何多余內容。

思路:0是怎么來的,2和5乘來的,所以求出因數2、5的個數,然后取最小值就好。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int two, five;
 5 
 6 void work(int x) {
 7     int xx = x;
 8     while(xx%2 == 0) {
 9         ++two;
10         xx /= 2;
11     }
12     while(xx%5 == 0) {
13         ++five;
14         xx /= 5;
15     }
16 }
17 
18 int main() {
19     for(int i=1; i<=100; ++i) {
20         int x; cin >> x;
21         work(x);
22     }
23     printf("%d\n", min(two, five));
24     return 0;
25 }
3.乘積尾零

答案:31

 

4.第幾個幸運數

到x星球旅行的游客都被發給一個整數,作為游客編號。
x星的國王有個怪癖,他只喜歡數字3,5和7。
國王規定,游客的編號如果只含有因子:3,5,7,就可以獲得一份獎品。

我們來看前10個幸運數字是:
3 5 7 9 15 21 25 27 35 45
因而第11個幸運數字是:49

小明領到了一個幸運數字 59084709587505,他去領獎的時候,人家要求他准確地說出這是第幾個幸運數字,否則領不到獎品。

請你幫小明計算一下,59084709587505是第幾個幸運數字。

需要提交的是一個整數,請不要填寫任何多余內容。

思路:枚舉3、5、7的個數,當乘積小於59084709587505時說明這個數是在其前面,所以計數器加1.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const long long N = 59084709587505;
 5 
 6 bool check(int x, int y, int z) {
 7     long long sum = 1;
 8     while(x--) {
 9         sum *= 3;
10         if(sum >= N) return false;
11     }
12     while(y--) {
13         sum *= 5;
14         if(sum >= N) return false;
15     }
16     while(z--) {
17         sum *= 7;
18         if(sum >= N) return false;
19     }
20     //printf("***%lld***\n", sum);
21     return true;
22 }
23 
24 int main() {
25     int n = 0;
26     for(int i=0; i<=31; ++i) {
27         for(int j=0; j<=20; ++j) {
28             for(int k=0; k<=17; ++k) {
29                 if(check(i, j, k)) n++; 
30             }
31         }
32     }
33     printf("%d\n", n);
34     return 0;
35 }
4.第幾個幸運數

答案:1905

 

5.打印圖形

如下的程序會在控制台繪制分形圖(就是整體與局部自相似的圖形)。

當n=1,2,3的時候,輸出如下:
請仔細分析程序,並填寫划線部分缺少的代碼。

n=1時:

 o 
ooo
 o 

n=2時:

    o    
   ooo   
    o    
 o  o  o 
ooooooooo
 o  o  o 
    o    
   ooo   
    o 

n=3時:

             o             
            ooo            
             o             
          o  o  o          
         ooooooooo         
          o  o  o          
             o             
            ooo            
             o             
    o        o        o    
   ooo      ooo      ooo   
    o        o        o    
 o  o  o  o  o  o  o  o  o 
ooooooooooooooooooooooooooo
 o  o  o  o  o  o  o  o  o 
    o        o        o    
   ooo      ooo      ooo   
    o        o        o    
             o             
            ooo            
             o             
          o  o  o          
         ooooooooo         
          o  o  o          
             o             
            ooo            
             o  

源程序:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 void show(char* buf, int w){
 5     int i,j;
 6     for(i=0; i<w; i++){
 7         for(j=0; j<w; j++){
 8             printf("%c", buf[i*w+j]==0? ' ' : 'o');
 9         }
10         printf("\n");
11     }
12 }
13 
14 void draw(char* buf, int w, int x, int y, int size){
15     if(size==1){
16         buf[y*w+x] = 1;
17         return;
18     }
19     
20     int n = _________________________ ; //填空
21     draw(buf, w, x, y, n);
22     draw(buf, w, x-n, y ,n);
23     draw(buf, w, x+n, y ,n);
24     draw(buf, w, x, y-n ,n);
25     draw(buf, w, x, y+n ,n);
26 }
27 
28 int main()
29 {
30     int N = 3;
31     int t = 1;
32     int i;
33     for(i=0; i<N; i++) t *= 3;
34     
35     char* buf = (char*)malloc(t*t);
36     for(i=0; i<t*t; i++) buf[i] = 0;
37     
38     draw(buf, t, t/2, t/2, t);
39     show(buf, t);
40     free(buf);
41     
42     return 0;
43 }

注意:只提交划線部分缺少的代碼,不要抄寫任何已經存在的代碼或符號。

答案:size/3

 

6.航班時間

【問題背景】
小h前往美國參加了藍橋杯國際賽。小h的女朋友發現小h上午十點出發,上午十二點到達美國,於是感嘆到“現在飛機飛得真快,兩小時就能到美國了”。

小h對超音速飛行感到十分恐懼。仔細觀察后發現飛機的起降時間都是當地時間。由於北京和美國東部有12小時時差,故飛機總共需要14小時的飛行時間。

不久后小h的女朋友去中東交換。小h並不知道中東與北京的時差。但是小h得到了女朋友來回航班的起降時間。小h想知道女朋友的航班飛行時間是多少。

【問題描述】
對於一個可能跨時區的航班,給定來回程的起降時間。假設飛機來回飛行時間相同,求飛機的飛行時間。

【輸入格式】
從標准輸入讀入數據。
一個輸入包含多組數據。

輸入第一行為一個正整數T,表示輸入數據組數。
每組數據包含兩行,第一行為去程的 起降 時間,第二行為回程的 起降 時間。
起降時間的格式如下

h1:m1:s1 h2:m2:s2

h1:m1:s1 h3:m3:s3 (+1)

h1:m1:s1 h4:m4:s4 (+2)
表示該航班在當地時間h1時m1分s1秒起飛,

第一種格式表示在當地時間 當日 h2時m2分s2秒降落
第二種格式表示在當地時間 次日 h3時m3分s3秒降落。
第三種格式表示在當地時間 第三天 h4時m4分s4秒降落。

對於此題目中的所有以 h:m:s 形式給出的時間, 保證 ( 0<=h<=23, 0<=m,s<=59 ).

【輸出格式】
輸出到標准輸出。

對於每一組數據輸出一行一個時間hh:mm:ss,表示飛行時間為hh小時mm分ss秒。
注意,當時間為一位數時,要補齊前導零。如三小時四分五秒應寫為03:04:05。

【樣例輸入】
3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)

【樣例輸出】
04:09:05
12:10:39
14:22:05

【限制與約定】
保證輸入時間合法,飛行時間不超過24小時。


資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms


請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。

注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。

提交程序時,注意選擇所期望的語言類型和編譯器類型。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int get() {
 5     char line[100] = {};
 6     cin.getline(line, 100);
 7     int h1, m1, s1, h2, m2, s2, d=0;
 8     if(strlen(line) == 17)
 9         sscanf(line, "%d:%d:%d %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);
10     else 
11         sscanf(line, "%d:%d:%d %d:%d:%d (+%d)", &h1, &m1, &s1, &h2, &m2, &s2, &d);
12     return (d*24+h2-h1)*3600 + (m2-m1) * 60 + s2-s1;
13 }
14 
15 int main() {
16     int T;
17     cin >> T; getchar();
18     while(T--) {
19         int time1 = get();
20         int time2 = get();
21         int t = (time2+time1) / 2;
22         printf("%02d:%02d:%02d\n", t/3600, t/60%60, t%60);
23     }
24     return 0;
25 }
6.航班時間

 

7.三體攻擊

【題目描述】
三體人將對地球發起攻擊。為了抵御攻擊,地球人派出了 A × B × C 艘戰艦,在太空中排成一個 A 層 B 行 C 列的立方體。其中,第 i 層第 j 行第 k 列的戰艦(記為戰艦 (i, j, k))的生命值為 d(i, j, k)。

三體人將會對地球發起 m 輪“立方體攻擊”,每次攻擊會對一個小立方體中的所有戰艦都造成相同的傷害。具體地,第 t 輪攻擊用 7 個參數 lat, rat, lbt, rbt, lct, rct, ht 描述;
所有滿足 i ∈ [lat, rat],j ∈ [lbt, rbt],k ∈ [lct, rct] 的戰艦 (i, j, k) 會受到 ht 的傷害。如果一個戰艦累計受到的總傷害超過其防御力,那么這個戰艦會爆炸。

地球指揮官希望你能告訴他,第一艘爆炸的戰艦是在哪一輪攻擊后爆炸的。

【輸入格式】
從標准輸入讀入數據。

第一行包括 4 個正整數 A, B, C, m;
第二行包含 A × B × C 個整數,其中第 ((i − 1)×B + (j − 1)) × C + (k − 1)+1 個數為 d(i, j, k);
第 3 到第 m + 2 行中,第 (t − 2) 行包含 7 個正整數 lat, rat, lbt, rbt, lct, rct, ht。

【輸出格式】
輸出到標准輸出。

輸出第一個爆炸的戰艦是在哪一輪攻擊后爆炸的。保證一定存在這樣的戰艦。

【樣例輸入】
2 2 2 3
1 1 1 1 1 1 1 1
1 2 1 2 1 1 1
1 1 1 2 1 2 1
1 1 1 1 1 1 2

【樣例輸出】
2

【樣例解釋】
在第 2 輪攻擊后,戰艦 (1,1,1) 總共受到了 2 點傷害,超出其防御力導致爆炸。

【數據約定】
對於 10% 的數據,B = C = 1;
對於 20% 的數據,C = 1;
對於 40% 的數據,A × B × C, m ≤ 10, 000;
對於 70% 的數據,A, B, C ≤ 200;
對於所有數據,A × B × C ≤ 10^6, m ≤ 10^6, 0 ≤ d(i, j, k), ht ≤ 10^9。


資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 2000ms


請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。

注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。

提交程序時,注意選擇所期望的語言類型和編譯器類型。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int A, B, C, m;
 5 bool flag = false;
 6 int val[1000001]; // 轉化成一維 
 7 
 8 int Read();
 9 
10 inline int get(int i, int j, int k) { // 坐標轉化 
11     return ((i-1)*B + (j-1))*C + k;
12 }
13 
14 void init() { // 讀入 
15     A = Read(); B = Read();
16     C = Read(); m = Read();
17     for(int i=1; i<=A; ++i)
18         for(int j=1; j<=B; ++j)
19             for(int k=1; k<=C; ++k)
20                 val[get(i, j, k)] = Read();
21 }
22 
23 void work() {
24     int lat, rat, lbt, rbt, lct, rct, ht;
25     lat = Read(); rat = Read();
26     lbt = Read(); rbt = Read();
27     lct = Read(); rct = Read();
28     ht = Read();
29     for(int i=lat; i<=rat; ++i)
30         for(int j=lbt; j<=rbt; ++j)
31             for(int k=lct; k<=rct; ++k) {
32                 val[get(i, j, k)] -= ht;
33                 if(val[get(i, j, k)] < 0) {
34                     flag = true;
35                     return ;
36                 }
37             }
38 }
39 
40 int main() {
41     init(); 
42     for(int i=1; i<=m; ++i) { // 邊讀入邊操作 
43         work();
44         if(flag) {
45             printf("%d\n", i);
46             break;
47         }
48     }
49     return 0;
50 }
51 
52 inline int Read() { // 快讀 
53     char ch = getchar();
54     int x = 0, f = 1;
55     while(ch<'0' || ch>'9') {
56         if(ch == '-') f = -1;
57         ch = getchar();
58     }
59     while(ch>='0' && ch<='9') {
60         x = x * 10 + ch - '0';
61         ch = getchar();
62     }
63     return x * f;
64 }
7.三體攻擊-暴力-超時

三維差分

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 const int MAXN = 1e6 + 1;
  5 LL A, B, C, m, a, b, c;
  6 LL cc[MAXN];  // 差分數組 
  7 LL d[MAXN];   // 原始血量 
  8 LL sum[MAXN]; // 差分數組前綴和 
  9 LL atk[MAXN][7]; // 攻擊數據
 10  
 11 int Read(); // 快讀 
 12 
 13 inline int get(int i, int j, int k) { // 坐標轉化 
 14     return ((i-1)*B + (j-1))*C + k;
 15 }
 16 
 17 void add(LL cc[], int i, int j, int k, int h) {
 18     if(i<a && j<b && k<c)
 19         cc[get(j, j, k)] += h;
 20     return;
 21 }
 22 
 23 bool check(LL sum[], const LL d[]) {
 24 // 求前綴和 
 25     for(int i=2; i<=A; ++i)
 26         for(int j=1; j<=B; ++j)
 27             for(int k=1; k<=C; ++k)
 28                 sum[get(i, j, k)] += sum[get(i-1, j, k)];
 29     for(int i=1; i<=A; ++i)
 30         for(int j=2; j<=B; ++j)
 31             for(int k=1; k<=C; ++k)
 32                 sum[get(i, j, k)] += sum[get(i, j-1, k)];
 33     for(int i=1; i<=A; ++i)
 34         for(int j=1; j<=B; ++j)
 35             for(int k=2; k<=C; ++k)
 36                 sum[get(i, j, k)] += sum[get(i, j, k-1)];
 37 // 判斷當前攻擊輪數下有沒有被攻破的
 38     for(int i=1; i<=A; ++i)
 39         for(int j=1; j<=B; ++j)
 40             for(int k=1; k<=C; ++k)
 41                 if(sum[get(i, j, k)] > d[get(i, j, k)]) // 戰艦(i, j, k)被攻破 
 42                     return true;
 43     return false;
 44 }
 45 
 46 void work(LL cc[], LL *atk, int x) {
 47 // 取出當前攻擊的參數 
 48     int la, ra, lb, rb, lc, rc, h;
 49     la = atk[1]; ra = atk[2];
 50     lb = atk[3]; rb = atk[4];
 51     lc = atk[5]; rc = atk[6];
 52     h = atk[7] * x;
 53 // 
 54     add(cc, la,      lb,   lc,    h); 
 55     add(cc, la,      rb+1, lc,   -h); 
 56     add(cc, la,      lb,   rc+1, -h); 
 57     add(cc, la,      rb+1, rc+1,  h); 
 58 
 59     add(cc, ra+1, lb,   lc,   -h); 
 60     add(cc, ra+1, rb+1, lc,    h); 
 61     add(cc, ra+1, lb,   rc+1,  h); 
 62     add(cc, ra+1, rb+1, rc+1, -h); 
 63 }
 64 
 65 void init() { // 讀入 
 66     A = Read(); B = Read();
 67     C = Read(); m = Read();
 68     a = A + 1, b = B + 1, c = C + 1;
 69     for(int i=1; i<=A; ++i) // 讀入原始血量 
 70         for(int j=1; j<=B; ++j)
 71             for(int k=1; k<=C; ++k)
 72                 d[get(i, j, k)] = Read();
 73     for(int i=1; i<=m; ++i) // 讀入攻擊數據 
 74         for(int j=1; j<=7; ++j)
 75             atk[i][j] = Read(); 
 76 }
 77 
 78 int solve() { // 二分 
 79     int l = 1, r = m, lastmid = 0;
 80 // 假設當前的mid攻破了,那么往左靠,減小mid,即減少攻擊的輪數 
 81 // 假設當前mid沒有攻破,那么往右靠,增加mid,即增加攻擊的輪數 
 82     while(l < m) {
 83         int mid = (l + r) >> 1;
 84 // 上一輪的攻擊次數小於當前的,說明上一次的攻擊輪數無法攻破,增加攻擊的輪數 
 85         if(lastmid < mid) 
 86             for(int i=lastmid+1; i<=mid; ++i)
 87                 work(cc, atk[i], 1); // 1 攻擊 
 88         
 89 // 上一輪的攻擊次數大於當前的,說明上一次攻破了,嘗試減少攻擊的輪數,回復一些血量 
 90         if(lastmid > mid) 
 91             for(int i=mid+1; i<=lastmid; ++i)
 92                 work(cc, atk[i], -1); // -1 回復 
 93 // 將差分數組cc,復制到前綴和數組sum 
 94         memcpy(sum, cc, sizeof(LL)*a*b*c);
 95 // check() 求差分數組的前綴和,同時與原始血量做比較,即判斷有沒有被攻破的 
 96         if(check(sum, d)) // 攻破了,向左移,嘗試減小攻擊輪數mid
 97             r = mid;
 98         else l = mid + 1; // 沒有攻破,向右移,增大攻擊輪數mid
 99         lastmid = mid; // 更新上一次的攻擊輪數 
100     }
101     return r-1;
102 }
103 
104 int main() {
105     init(); 
106     int Ans = solve();
107     printf("%d\n", Ans);
108     return 0;
109 }
110 
111 inline int Read() { // 快讀 
112     char ch = getchar();
113     int x = 0, f = 1;
114     while(ch<'0' || ch>'9') {
115         if(ch == '-') f = -1;
116         ch = getchar();
117     }
118     while(ch>='0' && ch<='9') {
119         x = x * 10 + ch - '0';
120         ch = getchar();
121     }
122     return x * f;
123 }
7.三體攻擊-三維差分

 

8.全球變暖

【題目描述】
你有一張某海域NxN像素的照片,"."表示海洋、"#"表示陸地,如下所示:

.......
.##....
.##....
....##.
..####.
...###.
.......

其中"上下左右"四個方向上連在一起的一片陸地組成一座島嶼。例如上圖就有2座島嶼。

由於全球變暖導致了海面上升,科學家預測未來幾十年,島嶼邊緣一個像素的范圍會被海水淹沒。具體來說如果一塊陸地像素與海洋相鄰(上下左右四個相鄰像素中有海洋),它就會被淹沒。

例如上圖中的海域未來會變成如下樣子:

.......
.......
.......
.......
....#..
.......
.......

請你計算:依照科學家的預測,照片中有多少島嶼會被完全淹沒。

【輸入格式】
第一行包含一個整數N。 (1 <= N <= 1000)
以下N行N列代表一張海域照片。

照片保證第1行、第1列、第N行、第N列的像素都是海洋。

【輸出格式】
一個整數表示答案。

【樣例輸入】
7
.......
.##....
.##....
....##.
..####.
...###.
.......

【樣例輸出】
1


資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms


請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。

注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。

提交程序時,注意選擇所期望的語言類型和編譯器類型。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n, tot, cnt[10010];
 5 char Map[1001][1001];
 6 bool vis[1001][1001];
 7 int u[4] = {-1, 0, 0, 1}, v[4] = {0, -1, 1, 0};
 8 
 9 bool check(int x, int y) {
10     if(vis[x][y]) return false;
11     if(x<0 || x>=n) return false;
12     if(y<0 || y>=n) return false;
13     return true;
14 }
15 
16 void dfs(int x, int y, int k) {
17     if(Map[x][y] == '.') return ;
18     if(vis[x][y]) return ;
19     vis[x][y] = true;
20     if (Map[x - 1][y] == '#' && Map[x + 1][y] == '#' && Map[x][y - 1] == '#' && Map[x][y+1] == '#')
21         cnt[k] ++;
22     for (int i = 0; i < 4; ++i) {
23         int xx = x + u[i];
24         int yy = y + v[i];
25         if(check(xx, yy))
26             dfs(xx, yy, k);
27     }
28 }
29 
30 int main() {
31     cin >> n;
32     for(int i=0; i<n; ++i)
33         scanf("%s", Map[i]);
34     memset(vis, false, sizeof(vis));
35     // dfs???????
36     for(int i=0; i<n; ++i)
37         for(int j=0; j<n; ++j)
38             if(Map[i][j]=='#' && !vis[i][j]) {
39                 dfs(i, j, tot);
40                 tot ++;
41             }
42     int sum = 0;
43     for(int i=0; i<tot; ++i)
44         if(cnt[i] == 0) sum ++;
45     cout << sum << endl;
46     return 0;
47 }
8.全球變暖

 

9.倍數問題

【題目描述】
眾所周知,小蔥同學擅長計算,尤其擅長計算一個數是否是另外一個數的倍數。但小蔥只擅長兩個數的情況,當有很多個數之后就會比較苦惱。現在小蔥給了你 n 個數,希望你從這 n 個數中找到三個數,使得這三個數的和是 K 的倍數,且這個和最大。數據保證一定有解。

【輸入格式】
從標准輸入讀入數據。

第一行包括 2 個正整數 n, K。
第二行 n 個正整數,代表給定的 n 個數。

【輸出格式】
輸出到標准輸出。
輸出一行一個整數代表所求的和。

【樣例入】
4 3
1 2 3 4

【樣例輸出】
9

【樣例解釋】
選擇2、3、4。

【數據約定】
對於 30% 的數據,n <= 100。
對於 60% 的數據,n <= 1000。
對於另外 20% 的數據,K <= 10。
對於 100% 的數據,1 <= n <= 10^5, 1 <= K <= 10^3,給定的 n 個數均不超過 10^8。


資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms


請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。

注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。

提交程序時,注意選擇所期望的語言類型和編譯器類型。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n, val[101010], K;
 5 int Max_sum = -99999999;
 6 
 7 int Read();
 8 
 9 bool check(int x) {
10     return !(x%K);
11 }
12 
13 int main() {
14     cin >> n >> K;
15     for(int i=1; i<n; ++i) val[i] = Read();
16     for(int i=1; i<=n; ++i) {
17         for(int j=1; j<=n; ++j) {
18             if(i == j) continue;
19             for(int k=1; k<=n; ++k) {
20                 if(i==k || j==k) continue;
21                 int sum = i + j + k;
22                 if(check(sum) && sum>Max_sum) {
23                     Max_sum = sum;
24                 }
25             }
26         }
27     }
28     printf("%d\n", Max_sum);
29     return 0;
30 }
31 
32 inline int Read() {
33     int x, f = 1;
34     char ch = getchar();
35     while(ch<'0' || ch>'9') {
36         if(ch == '-') f = -1;
37         ch = getchar();
38     }
39     while(ch>='0' && ch <='9') {
40         x = x * 10 + ch - '0';
41         ch = getchar();
42     }
43     return x * f;
44 }
9.倍數問題-暴力-超時

思路:按照余數分組,對於相同的余數只保留前三大,然后枚舉。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int N, K;
 5 int group[1001][4];
 6 int Read();
 7 
 8 void Insert(int pos, int val) {
 9     group[pos][3] = val;
10     for(int i=2; i>=0; --i) {
11         if(group[pos][i+1] > group[pos][i])
12             swap(group[pos][i+1], group[pos][i]);
13     }
14 }
15 
16 int main() {
17     cin >> N >> K;
18     for(int i=1; i<=N; ++i) { // 分組 
19         int x; x = Read();
20         int re = x % K;
21         Insert(re, x);
22     }
23     long long Ans = 0, v1, v2, v3;
24     for(int i=0; i<K; ++i) {
25         for(int j=0; j<K; ++j) {
26             int kk = (2*K - i - j) % K;
27             v1 = group[i][0]; // v1是第一個數 
28             if(i == j) { // i j相同 v2是第二個數 
29                 v2 = group[i][1];
30                 // 都相同 v3是該余數下第三個數
31                 if(i == kk) v3 = group[i][2]; 
32                 // 不相同 v3是第一個數 
33                 else v3 = group[kk][0];
34             }
35             else { // i j 不相同  
36                 v2 = group[j][0];
37                 // 和i相同 第二個數 
38                 if(i == kk) v3 = group[i][1];
39                 // 和j相同 第二個數 
40                 else if(j == kk) v3 = group[j][1];
41                 // 和i相同 第二個數 
42                 else v3 = group[kk][0];
43             } 
44             long long tmp = v1 + v2 + v3;
45             if(tmp > Ans) Ans = tmp;
46         }
47     }
48     printf("%lld\n", Ans);
49     return 0;
50 }
51 
52 inline int Read() {
53     int x = 0, f = 1;
54     char ch = getchar();
55     while(ch<'0' || ch>'9') {
56         if(ch == '-') f = -1;
57         ch = getchar();
58     }
59     while(ch>='0' && ch <='9') {
60         x = x * 10 + ch - '0';
61         ch = getchar();
62     }
63     return x * f;
64 }
9.倍數問題

 

10.付賬問題

【題目描述】
幾個人一起出去吃飯是常有的事。但在結帳的時候,常常會出現一些爭執。

現在有 n 個人出去吃飯,他們總共消費了 S 元。其中第 i 個人帶了 ai 元。幸運的是,所有人帶的錢的總數是足夠付賬的,但現在問題來了:每個人分別要出多少錢呢?

為了公平起見,我們希望在總付錢量恰好為 S 的前提下,最后每個人付的錢的標准差最小。這里我們約定,每個人支付的錢數可以是任意非負實數,即可以不是1分錢的整數倍。你需要輸出最小的標准差是多少。

標准差的介紹:標准差是多個數與它們平均數差值的平方平均數,一般用於刻畫這些數之間的“偏差有多大”。形式化地說,設第 i 個人付的錢為 bi 元,那么標准差為 : [參見p1.png]

【輸入格式】
從標准輸入讀入數據。

第一行包含兩個整數 n、S;
第二行包含 n 個非負整數 a1, ..., an。

【輸出格式】
輸出到標准輸出。

輸出最小的標准差,四舍五入保留 4 位小數。
保證正確答案在加上或減去 10^−9 后不會導致四舍五入的結果發生變化。

【樣例1輸入】
5 2333
666 666 666 666 666

【樣例輸出】
0.0000

【樣例解釋】
每個人都出 2333/5 元,標准差為 0。

再比如:
【樣例輸入】
10 30
2 1 4 7 4 8 3 6 4 7

【樣例輸出】
0.7928

【數據說明】
對於 10% 的數據,所有 ai 相等;
對於 30% 的數據,所有非 0 的 ai 相等;
對於 60% 的數據,n ≤ 1000;
對於 80% 的數據,n ≤ 10^5;
對於所有數據,n ≤ 5 × 10^5, 0 ≤ ai ≤ 10^9。


資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms


請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。

注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。

提交程序時,注意選擇所期望的語言類型和編譯器類型。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4  
 5 LL N, S;
 6 LL Money[501010];
 7 double Avg, Ans;
 8 
 9 int main() {
10     cin >> N >> S;
11     Avg = S*1.0 / N; // 總平均數 
12     for(int i=0; i<N; ++i)
13         scanf("%lld", &Money[i]);
14     sort(Money, Money+N);
15     
16     for(int i=0; i<N; ++i) {
17     //第i個人的錢 * 目前剩余的人 < 應付的錢  第i個人全付 
18         if(Money[i] * (N-i) < S) { 
19         // 累加到方差 
20             Ans += (Money[i] - Avg) * (Money[i] - Avg);
21             S -= Money[i]; 
22         }
23     // 由於按升序排序,當前人的錢多余平均數時 說明后面的人也都多余平均數
24     // 那么對剩下的人單獨求平均數 然后每個人都出那么多 
25         else {
26             double tmp = S*1.0 / (N-i);
27             Ans += (tmp-Avg) * (tmp-Avg) * (N-i); 
28             break;
29         }
30     }
31     printf("%.4lf\n", sqrt(Ans/N));
32     return 0;
33 }
10.付賬問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM