題目一覽:
1.第幾天
2.明碼
3.乘積尾零
4.測試次數
5.快速排序
6.遞增三元組
7.螺旋折線
8.日志統計
9.全球變暖
10.乘積最大
1.第幾天
2000年的1月1日,是那一年的第1天。
那么,2000年的5月4日,是那一年的第幾天?
注意:需要提交的是一個整數,不要填寫任何多余內容。

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() { 5 int days = 31 + 29 + 31 + 30 + 4; 6 printf("%d\n", days); 7 return 0; 8 }
答案:125
2.明碼
漢字的字形存在於字庫中,即便在今天,16點陣的字庫也仍然使用廣泛。
16點陣的字庫把每個漢字看成是16x16個像素信息。並把這些信息記錄在字節中。
一個字節可以存儲8位信息,用32個字節就可以存一個漢字的字形了。
把每個字節轉為2進制表示,1表示墨跡,0表示底色。每行2個字節,
一共16行,布局是:
第1字節,第2字節
第3字節,第4字節
....
第31字節, 第32字節
這道題目是給你一段多個漢字組成的信息,每個漢字用32個字節表示,這里給出了字節作為有符號整數的值。
題目的要求隱藏在這些信息中。你的任務是復原這些漢字的字形,從中看出題目的要求,並根據要求填寫答案。
這段信息是(一共10個漢字):
4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 0 16 64 16 64 34 68 127 126 66 -124 67 4 66 4 66 -124 126 100 66 36 66 4 66 4 66 4 126 4 66 40 0 16 4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 0 0 -128 64 -128 48 -128 17 8 1 -4 2 8 8 80 16 64 32 64 -32 64 32 -96 32 -96 33 16 34 8 36 14 40 4 4 0 3 0 1 0 0 4 -1 -2 4 0 4 16 7 -8 4 16 4 16 4 16 8 16 8 16 16 16 32 -96 64 64 16 64 20 72 62 -4 73 32 5 16 1 0 63 -8 1 0 -1 -2 0 64 0 80 63 -8 8 64 4 64 1 64 0 -128 0 16 63 -8 1 0 1 0 1 0 1 4 -1 -2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 5 0 2 0 2 0 2 0 7 -16 8 32 24 64 37 -128 2 -128 12 -128 113 -4 2 8 12 16 18 32 33 -64 1 0 14 0 112 0 1 0 1 0 1 0 9 32 9 16 17 12 17 4 33 16 65 16 1 32 1 64 0 -128 1 0 2 0 12 0 112 0 0 0 0 0 7 -16 24 24 48 12 56 12 0 56 0 -32 0 -64 0 -128 0 0 0 0 1 -128 3 -64 1 -128 0 0
注意:需要提交的是一個整數,不要填寫任何多余內容。
思路:就是一題模擬題,把數字轉化成二進制輸出就好。值得注意的是負數怎么求它的補碼。1.先求出負數的絕對值的二進制,然后從有到左遍歷,遇到第一個1時,將其左側全部取反,右側和它本身不變。例如01100100 -> 10011100

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 void work(int x) { 5 int arr[15], flag = 0; 6 if(x < 0) flag = 1, x=-x; 7 for(int i=0; i<=7; ++i) { 8 arr[i] = x%2; 9 x /= 2; 10 } 11 if(flag) // 負數 12 for(int i=0; i<=7; ++i) 13 if(arr[i]==1 && i<7) { 14 for(int j=i+1; j<=7; ++j) 15 arr[j] = 1 - arr[j]; 16 break; 17 } 18 for(int i=7; i>=0; --i) { 19 if(arr[i] == 0) printf(" "); 20 else printf("*"); 21 } 22 } 23 24 int main() { 25 int i = 10; 26 while(i--) { 27 for(int j=1; j<=16; ++j) { 28 int a; 29 scanf("%d", &a); 30 work(a); 31 scanf("%d", &a); 32 work(a); 33 printf("\n"); 34 } 35 printf("\n"); 36 printf("\n"); 37 } 38 return 0; 39 }
答案:387420489
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 } 26 // 31
答案:31
4.測試次數
x星球的居民脾氣不太好,但好在他們生氣的時候唯一的異常舉動是:摔手機。
各大廠商也就紛紛推出各種耐摔型手機。x星球的質監局規定了手機必須經過耐摔測試,並且評定出一個耐摔指數來,之后才允許上市流通。
x星球有很多高聳入雲的高塔,剛好可以用來做耐摔測試。塔的每一層高度都是一樣的,與地球上稍有不同的是,他們的第一層不是地面,而是相當於我們的2樓。
如果手機從第7層扔下去沒摔壞,但第8層摔壞了,則手機耐摔指數=7。
特別地,如果手機從第1層扔下去就壞了,則耐摔指數=0。
如果到了塔的最高層第n層扔沒摔壞,則耐摔指數=n
為了減少測試次數,從每個廠家抽樣3部手機參加測試。
某次測試的塔高為1000層,如果我們總是采用最佳策略,在最壞的運氣下最多需要測試多少次才能確定手機的耐摔指數呢?
請填寫這個最多測試次數。
注意:需要填寫的是一個整數,不要填寫任何多余內容。

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1000; 5 6 // N層 3個手機 7 int f[4][N+1]; 8 9 10 int main() { 11 // f1 1部手機 12 for(int i=0; i<=N; ++i) f[1][i] = i; 13 14 //f2 2部手機 15 for(int i=1; i<=N; ++i) { // 第i層 16 // 嘗試從第j層開始扔 17 int Max = 1 << 31, Min = 1 << 30; 18 for(int j=1; j<=i; ++j) { 19 int ok = f[2][i-j] + 1; // 沒壞 還是2個手機 往上測試i-j層 20 int fail = f[1][j-1] + 1; // 壞了 還剩1個手機 還有j-1層 21 Max = max(ok, fail); // 最壞取大值 22 Min = min(Min, Max); // 最優取較小值 23 } 24 f[2][i] = Min; 25 } 26 27 //f3 3部手機 28 for(int i=1; i<=N; ++i) { // 第i層 29 // 嘗試從第j層開始扔 30 int Max = 1<<31, Min = 1 << 30; 31 for(int j=1; j<=i; ++j) { 32 int ok = f[3][i-j] + 1; // 沒壞 還是2個手機 往上測試i-j層 33 int fail = f[2][j-1] + 1; // 壞了 還剩1個手機 還有j-1層 34 Max = max(ok, fail); // 最壞取大值 35 Min = min(Min, Max); // 最優取較小值 36 } 37 f[3][i] = Min; 38 } 39 printf("%d\n", f[3][N]); 40 return 0; 41 }
答案:19
5.快速排序
以下代碼可以從數組a[]中找出第k小的元素。
它使用了類似快速排序中的分治算法,期望時間復雜度是O(N)的。
請仔細閱讀分析源碼,填寫划線部分缺失的內容。
1 #include <stdio.h> 2 3 int quick_select(int a[], int l, int r, int k) { 4 int p = rand() % (r - l + 1) + l; 5 int x = a[p]; 6 {int t = a[p]; a[p] = a[r]; a[r] = t;} 7 int i = l, j = r; 8 while(i < j) { 9 while(i < j && a[i] < x) i++; 10 if(i < j) { 11 a[j] = a[i]; 12 j--; 13 } 14 while(i < j && a[j] > x) j--; 15 if(i < j) { 16 a[i] = a[j]; 17 i++; 18 } 19 } 20 a[i] = x; 21 p = i; 22 if(i - l + 1 == k) return a[i]; 23 if(i - l + 1 < k) return quick_select( _____________________________ ); //填空 24 else return quick_select(a, l, i - 1, k); 25 } 26 27 int main() 28 { 29 int a[] = {1, 4, 2, 8, 5, 7, 23, 58, 16, 27, 55, 13, 26, 24, 12}; 30 printf("%d\n", quick_select(a, 0, 14, 5)); 31 return 0; 32 }
注意:只填寫划線部分缺少的代碼,不要抄寫已經存在的代碼或符號。
答案:
a, i+1, r, k-i+l-1
6.遞增三元組
給定三個整數數組
A = [A1, A2, ... AN],
B = [B1, B2, ... BN],
C = [C1, C2, ... CN],
請你統計有多少個三元組(i, j, k) 滿足:
1. 1 <= i, j, k <= N
2. Ai < Bj < Ck
【輸入格式】
第一行包含一個整數N。
第二行包含N個整數A1, A2, ... AN。
第三行包含N個整數B1, B2, ... BN。
第四行包含N個整數C1, C2, ... CN。
對於30%的數據,1 <= N <= 100
對於60%的數據,1 <= N <= 1000
對於100%的數據,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000
【輸出格式】
一個整數表示答案
【樣例輸入】
3
1 1 1
2 2 2
3 3 3
【樣例輸出】
27
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。
提交程序時,注意選擇所期望的語言類型和編譯器類型。
1.按照題目要求直接做

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 100001; 4 5 int n; 6 int A[N], B[N], C[N]; 7 long long Ans; 8 9 int Read(); 10 11 int main() { 12 cin >> n; 13 for(int i=1; i<=n; ++i) A[i] = Read(); 14 for(int i=1; i<=n; ++i) B[i] = Read(); 15 for(int i=1; i<=n; ++i) C[i] = Read(); 16 for(int i=1; i<=n; ++i) 17 for(int j=1; j<=n; ++j) 18 for(int k=1; k<=n; ++k) 19 if(A[i]<B[j] && B[j]<C[k]) 20 Ans ++; 21 printf("%lld\n", Ans); 22 return 0; 23 } 24 25 inline int Read() { 26 int x = 0, f = 1; 27 char ch = getchar(); 28 while(ch<'0' || ch>'9') { 29 if(ch == '-') f = -1; 30 ch = getchar(); 31 } 32 while(ch>='0' && ch<='9') { 33 x = x * 10 + ch - '0'; 34 ch = getchar(); 35 } 36 return x * f; 37 }
2.由於這個和順序沒有關系,我們可以對這三個數組排序,然后枚舉B數組的每一個值當做中間值,在A數組中找比他小的,在C中找小於等於的,然后與總數做差的大於的數,然后相乘即可。

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 100001; 4 5 int n; 6 int A[N], B[N], C[N]; 7 long long Ans; 8 9 int Read(); 10 11 int main() { 12 cin >> n; 13 for(int i=0; i<n; ++i) A[i] = Read(); 14 for(int i=0; i<n; ++i) B[i] = Read(); 15 for(int i=0; i<n; ++i) C[i] = Read(); 16 sort(A, A+n); 17 sort(B, B+n); 18 sort(C, C+n); 19 for(int i=0, j=0, k=0; j<n; ++j) { 20 while(i<n && A[i]<B[j]) i++; 21 while(k<n && C[k]<=B[j]) k++; 22 Ans += (long long)i * (n-k); 23 } 24 printf("%lld\n", Ans); 25 return 0; 26 } 27 28 inline int Read() { 29 int x = 0, f = 1; 30 char ch = getchar(); 31 while(ch<'0' || ch>'9') { 32 if(ch == '-') f = -1; 33 ch = getchar(); 34 } 35 while(ch>='0' && ch<='9') { 36 x = x * 10 + ch - '0'; 37 ch = getchar(); 38 } 39 return x * f; 40 }
7.螺旋折線
如圖p1.png所示的螺旋折線經過平面上所有整點恰好一次。
對於整點(X, Y),我們定義它到原點的距離dis(X, Y)是從原點到(X, Y)的螺旋折線段的長度。
例如dis(0, 1)=3, dis(-2, -1)=9
給出整點坐標(X, Y),你能計算出dis(X, Y)嗎?
【輸入格式】
X和Y
對於40%的數據,-1000 <= X, Y <= 1000
對於70%的數據,-100000 <= X, Y <= 100000
對於100%的數據, -1000000000 <= X, Y <= 1000000000
【輸出格式】
輸出dis(X, Y)
【樣例輸入】
0 1
【樣例輸出】
3
資源約定:
峰值內存消耗(含虛擬機) < 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 X, Y; 6 7 LL sum(LL a0, LL n, LL d) { 8 return (2*a0 + ((n)-1) * d) * n / 2; 9 } 10 11 int main() { 12 cin >> X >> Y; 13 LL d = 0, n = 0; 14 if(Y>0 && abs(X)<=Y) { 15 n = Y; 16 d = Y - X + 2 * Y; 17 } 18 else if(X>0 && abs(Y)<=X) { 19 n = X; 20 d = X + Y; 21 } 22 else if(Y<=0 && X>=Y-1 && X<=-Y) { 23 n = -Y; 24 d = -(-Y-X); 25 } 26 else if(X<0 && Y>=X+1 && Y<=-X) { 27 n = -X-1; 28 d = -(Y-X-1-2*X-1); 29 } 30 LL Ans = sum(1, 2*n, 1) * 2 - d; 31 cout << Ans << endl; 32 return 0; 33 }
8.日志統計
小明維護着一個程序員論壇。現在他收集了一份"點贊"日志,日志共有N行。其中每一行的格式是:
ts id
表示在ts時刻編號id的帖子收到一個"贊"。
現在小明想統計有哪些帖子曾經是"熱帖"。如果一個帖子曾在任意一個長度為D的時間段內收到不少於K個贊,小明就認為這個帖子曾是"熱帖"。
具體來說,如果存在某個時刻T滿足該帖在[T, T+D)這段時間內(注意是左閉右開區間)收到不少於K個贊,該帖就曾是"熱帖"。
給定日志,請你幫助小明統計出所有曾是"熱帖"的帖子編號。
【輸入格式】
第一行包含三個整數N、D和K。
以下N行每行一條日志,包含兩個整數ts和id。
對於50%的數據,1 <= K <= N <= 1000
對於100%的數據,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000
【輸出格式】
按從小到大的順序輸出熱帖id。每個id一行。
【輸入樣例】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
【輸出樣例】
1
3
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。
提交程序時,注意選擇所期望的語言類型和編譯器類型。

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct R { 5 int ts, td; 6 }; 7 8 bool cmp(R a, R b) { 9 return a.ts < b.ts; 10 } 11 12 int N, D, K; 13 14 int main() { 15 cin >> N >> D >> K; 16 vector<R> records(N); 17 map<int, int> cnt; 18 for(int i=0; i<N; ++i) { 19 scanf("%d%d", &records[i].ts, &records[i].td); 20 } 21 sort(records.begin(), records.end(), cmp); 22 set<int> ans; 23 for(int i=0, j=0; i<N; ++i) { 24 while(j<N && records[j].ts-records[i].ts<D) { 25 cnt[records[j].td] ++; 26 if(cnt[records[j].td] >= K) 27 ans.insert(records[j].td); 28 j++; 29 } 30 cnt[records[i].td] --; 31 } 32 for(set<int>::iterator i=ans.begin(); i!=ans.end(); ++i) 33 printf("%d\n", *i); 34 return 0; 35 }
9.全球變暖
【題目描述】
你有一張某海域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 }
10.乘積最大
給定N個整數A1, A2, ... AN。請你從中選出K個數,使其乘積最大。
請你求出最大的乘積,由於乘積可能超出整型范圍,你只需輸出乘積除以1000000009的余數。
注意,如果X<0, 我們定義X除以1000000009的余數是負(-X)除以1000000009的余數。
即:0-((0-x) % 1000000009)
【輸入格式】
第一行包含兩個整數N和K。
以下N行每行一個整數Ai。
對於40%的數據,1 <= K <= N <= 100
對於60%的數據,1 <= K <= 1000
對於100%的數據,1 <= K <= N <= 100000 -100000 <= Ai <= 100000
【輸出格式】
一個整數,表示答案。
【輸入樣例】
5 3
-100000
-10000
2
100000
10000
【輸出樣例】
999100009
再例如:
【輸入樣例】
5 3
-100000
-100000
-2
-100000
-100000
【輸出樣例】
-999999829
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。
提交程序時,注意選擇所期望的語言類型和編譯器類型。
思路:
N個數選K個 K<=N 設負數cnt1個,正數cnt2個,負數、正數一共cnt個 1.cnt<K,必須選0, Ans = 0 2.cnt==K, 2.1 K(cnt)==N,全是正負數。Ans = 正數積 * 負數積 2.2 K<N 有0的存在 2.2.1 cnt1為偶數,Ans = 全部相乘 2.2.2 cnt1是奇數,Ans = 0 3.cnt>K 3.1 全是負數 3.1.1 K是偶數,Ans = 絕對值最大的K個負數相乘 3.1.2 K是奇數 3.1.2.1 cnt<N,表示有0, Ans = 0 3.1.2.2 cnt==N,Ans = 絕對值最小的K個負數相乘 3.2 全是正數 Ans = 最大的K個數相乘 3.3 正負都有 3.3.1 正數不足K個(假設正數全選) 3.3.1.1 K-cnt2是偶數,游標:正的0~末尾,負的0-K-cnt2-1 3.3.1.2 K-cnt2是奇數,游標:正的1~末尾,負的0-K-cnt2 3.3.2 正數個數不小於K,游標 正的cnt2-K~末尾,負的0~0

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL Mod = 1e9 + 9; 6 7 LL N, K, Ans; 8 vector<LL> pos, neg; 9 10 LL mul(vector<LL> a, int x, int y) { 11 LL tmp = 1; 12 for(int i=x; i<=y; ++i) 13 tmp = tmp * a[i] % Mod; 14 return tmp; 15 } 16 17 int main() { 18 cin >> N >> K; 19 for(int i=1; i<=N; ++i) { 20 LL x; scanf("%lld", &x); 21 if(x > 0) pos.push_back(x); 22 if(x < 0) neg.push_back(x); 23 } 24 sort(pos.begin(), pos.end()); 25 sort(neg.begin(), neg.end()); 26 LL cnt = pos.size() + neg.size(); 27 if(cnt < K) Ans = 0; // 非0數的個數不夠K個,要補0,答案是0 28 else if(cnt == K) { // 非0數的個數剛好K個 29 if(K == N) // K等於N,都不是0,全部乘起來 30 Ans = mul(pos, 0, pos.size()-1) * mul(neg, 0, neg.size()-1) % Mod; 31 else { // 說明有0, 32 if(neg.size()%2 == 0) // 負數有偶數個 可以全部乘起來 33 Ans = mul(pos, 0, pos.size()-1) * mul(neg, 0, neg.size()-1) % Mod; 34 else Ans = 0; // 負數是奇數個,保證結果最大只能加個0 35 } 36 } 37 else { // 非0數富裕 38 if(pos.size() == 0) { // 全是負數 39 if(K%2 == 0) // 選偶數個,選絕對值大的 40 Ans = mul(neg, 0, K-1); 41 else { // 選奇數個 42 if(cnt < N) // 有0 43 Ans = 0; 44 else // 沒有 0 答案會是負數 選絕對值小的 45 Ans = mul(neg, neg.size()-K, neg.size()-1); 46 } 47 } 48 else if(neg.size() == 0) // 全是正數 選K個大的 49 Ans = (pos, pos.size()-K, pos.size()-1); 50 else { // 有正有負 51 int posStart, negEnd; 52 if(pos.size() < K) { // 正數不足K個 53 if((K-pos.size())%2 == 0) { // 還剩偶數個位置 54 posStart = 0; 55 negEnd = K - pos.size() - 1; 56 } 57 else { // 還剩奇數個位置 58 posStart = 1; // 減少一個正數 給負數的位置湊夠偶數個 59 negEnd = K - pos.size(); // 不然這個正數再大結果都是負的 60 } 61 } 62 else { // 正數大於等於K個 63 posStart = pos.size() - K; 64 negEnd = -1; 65 } 66 // 開始移動 67 while(negEnd+2<neg.size() && posStart+2<pos.size()) { // 還能移動就嘗試移動 68 // 負數替換正數沒有價值了 69 if(neg[negEnd+1]*neg[negEnd+2] <= pos[posStart]*pos[posStart+1]) break; 70 negEnd += 2; 71 posStart += 2; 72 } 73 // 求好了正負數的個數 開始求積 74 Ans = mul(pos, posStart, pos.size()-1) * mul(neg, 0, negEnd) % Mod; 75 } 76 } 77 cout << Ans << endl; 78 return 0; 79 }