2018第九屆藍橋杯 C/C++ B組省賽

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/lcuwb/article/details/79795047


第一題、第幾天

題目描述:

標題:第幾天

2000年的1月1日,是那一年的第1天。
那麼,2000年的5月4日,是那一年的第幾天?


注意:需要提交的是一個整數,不要填寫任何多餘內容。

題目分析:

答案: 125

藍橋杯考過幾次日期的問題了吧, 打開Excel或者計算器都可以直接計算。

第二題、明碼

題目描述:

標題:明碼

漢字的字形存在於字庫中,即便在今天,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 


注意:需要提交的是一個整數,不要填寫任何多餘內容。

題目分析:

比較新穎的一個題目, 一開始看到題我是有點懵逼的, 就跳過去了, 做了大題之後又回來做的,題目都說了三十二個字節表示一個數, 我沒細讀題, 我還數了數第一行幾個數, 果然!! 自己有點傻了··· 然後就是一行倆字節唄, 然後按二進制進行過寫0或者1

輸出就可以看到了。 結果是:九的九次方等於多少?

#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
	int x;
	FILE * fb = fopen("data.txt", "w");
	for(int i=0; i<10; ++i)
	{
		for(int j=0; j<32; ++j)
		{
			scanf("%d", &x);
			for(int k=7; k>=0; --k)
				if((x >> k) & 1) fprintf(fb, "1");
				else fprintf(fb, " ");
			if(j%2) fprintf(fb, "\n");
		}
	}
	return 0;
}

結果

答案: 387420489

第四題、乘積尾零

題目描述:

如下的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 

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

題目分析:

一開始我想不就這麼寫數嗎, 我直接對10的十八次方取餘不就行了, 然後取餘結果是0···· 原來這麼大。 想想高精度多麻煩啊。待會做吧。

做了會別的之後就想到了。 每次乘一個數直接判斷後面的0的個數即可, 有0就除10, cnt+1. 反正後面的0做乘法不影響。

然後發現死循環(賽場上我記得沒取餘啊, 忘了當時怎麼寫的了), 輸出一下越界了, 那就取餘, 因爲後面變0, 只跟最後的數有關, 前面無所謂。

還有另一個解法, 就是數數有幾個5和2, 這個我沒試, 應該可以。

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
	long long x, cur = 1;
	int cnt = 0;
	for(int i = 0; i<100; ++i)
	{
		scanf("%lld", &x);
		cur *= x;
		while(cur % 10 == 0)
		{
			cnt++;
			cur /= 10;
			//cout << cur << endl;	
		}
		cur %= 1000000000;
	}
	cout << cnt << endl;
	return 0;
}

答案: 31

第四題、測試次數

題目描述:

x星球的居民脾氣不太好,但好在他們生氣的時候唯一的異常舉動是:摔手機。
各大廠商也就紛紛推出各種耐摔型手機。x星球的質監局規定了手機必須經過耐摔測試,並且評定出一個耐摔指數來,之後才允許上市流通。

x星球有很多高聳入雲的高塔,剛好可以用來做耐摔測試。塔的每一層高度都是一樣的,與地球上稍有不同的是,他們的第一層不是地面,而是相當於我們的2樓。

如果手機從第7層扔下去沒摔壞,但第8層摔壞了,則手機耐摔指數=7。
特別地,如果手機從第1層扔下去就壞了,則耐摔指數=0。
如果到了塔的最高層第n層扔沒摔壞,則耐摔指數=n

爲了減少測試次數,從每個廠家抽樣3部手機參加測試。

某次測試的塔高爲1000層,如果我們總是採用最佳策略,在最壞的運氣下最多需要測試多少次才能確定手機的耐摔指數呢?

請填寫這個最多測試次數。

注意:需要填寫的是一個整數,不要填寫任何多餘內容。

題目分析:

當時拿到問題的時候一看, 這不是二分嗎, 太簡單了吧, 然後想了想不對啊, 二分需要十個手機, 然後就果斷放棄了…先做後面的, 拿分要緊。 後來想想是個dp
思路:
 每次策略都是最優的, 而每次運氣都是最壞的, 手機又是有限的, 那麼一開始扔的第一個手機就很關鍵, 高了浪費手機, 低了浪費次數, 至於中間, 不是想過二分了嗎, 太高, 所以就需要試一下從哪一層扔。
先假設只有一部手機, 那麼辦法只能一層一層的試。
兩部手機的話, 我是不是可以從第k層扔, 那麼如果碎了,答案肯定在前k層裏, 這樣我就再試k次就行了, 最壞情況是沒壞, 扔最後k層了, 他碎了, 所以前面的k應該大一點, 後面的應該小一點。 沒法確定, 那麼枚舉唄。
三部手機的話, 我也是從k層扔, 如果碎了, 就變成了兩部手機, k層的問題, 沒碎, 就是三部手機 n-k的問題, 構成了遞推公式, 前面已知的情況, 就可以記憶化搜索了。
這樣我們就只需要枚舉我們從哪一層扔是最優解就行了。

#include <iostream>
#include <algorithm>

using namespace std;

int dp[1005][4];

const int INF = (1 << 31) - 1;

int solve(int n, int cnt)
{
	if(n <= 0 || cnt <= 0) return INF;
	if(dp[n][cnt]) return dp[n][cnt];

	//最壞策略是 n-1層試了幾次, 沒出結果, 所以肯定還有手機沒壞, 我再在第n層試一次
	dp[n][cnt] = solve(n-1, cnt) + 1;

	//現在找最優策略
	//當我從第i層扔下去的時候有兩種情況
	//1. 碎了, 那麼我就要用cnt-1個手機去試前i層的情況, 即dfs(i-1, cnt-1)
	//2. 沒碎, 那麼我就只需要關心i上面的 n-i層即可, 即dfs(n-i, cnt)
	//由於我在第i層試了一次, 所以這兩種情況都要加1
	//枚舉所有的i
	for(int i=1; i<n; ++i)
		dp[n][cnt] = min(dp[n][cnt], max(solve(i-1, cnt-1), solve(n-i, cnt)) + 1);

	return dp[n][cnt];
}


int main()
{
	//不管幾個手機, 只有一層的話都只需要扔一次就行了
	for(int i=0; i<1005; ++i)
		dp[i][1] = i;

	cout << solve(1000, 3) << endl;
	return 0;
}



第五題、快速排序

題目描述:

標題:快速排序。 

以下代碼可以從數組a[]中找出第k小的元素。


它使用了類似快速排序中的分治算法,期望時間複雜度是O(N)的。


請仔細閱讀分析源碼,填寫劃線部分缺失的內容。

#include <stdio.h>

int quick_select(int a[], int l, int r, int k) {
	int p = rand() % (r - l + 1) + l;
	int x = a[p];
	{int t = a[p]; a[p] = a[r]; a[r] = t;}
	int i = l, j = r;
	while(i < j) {
		while(i < j && a[i] < x) i++;
		if(i < j) {
			a[j] = a[i];
			j--;
		}
		while(i < j && a[j] > x) j--;
		if(i < j) {
			a[i] = a[j];
			i++;
		}
	}
	a[i] = x;
	p = i;
	if(i - l + 1 == k) return a[i];
	if(i - l + 1 < k) return quick_select( _____________________________ ); //填空
	else return quick_select(a, l, i - 1, k);
}
	
int main()
{
	int a[] = {1, 4, 2, 8, 5, 7, 23, 58, 16, 27, 55, 13, 26, 24, 12};
	printf("%d\n", quick_select(a, 0, 14, 5));
	return 0;
}


注意:只填寫劃線部分缺少的代碼,不要抄寫已經存在的代碼或符號。

題目分析:

沒啥好說的, 又是遞歸, 注意一下時間複雜度即可。

答案: a, i+1, r, r-(i-l+1)

第六題、遞增三元組

題目描述:

給定三個整數數組
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 

題目分析:

水題, 直接快排, 然後順着找即可。 每找到一個符合的, 那後面一定都符合, 直接乘即可。

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 100000 +5;

long long A[maxn], B[maxn], C[maxn];

int main()
{
	int n;
	scanf("%d", &n);
	for(int i=0; i<n; ++i) scanf("%lld", &A[i]);
	for(int i=0; i<n; ++i) scanf("%lld", &B[i]);
	for(int i=0; i<n; ++i) scanf("%lld", &C[i]);
	
	sort(A, A+n);
	sort(B, B+n);
	sort(C, C+n);
	long long sum = 0;
	for(int i=0, j=0, k=0; i<n; ++i)
	{
		while(B[j] <= A[i]) ++j;
		while(C[k] <= B[i]) ++k;
		if(A[i] < B[j] && B[j] < C[k]) sum += (n-j) * (n-k);
	}
	printf("%lld\n", sum);
				
	return 0;
}

第七題 螺旋折線

題目描述

如圖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>
不能通過工程設置而省略常用頭文件。

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

在這裏插入圖片描述

題目分析

可以吧折線分成四個區域, 分別是四個角的方向上, 因爲四個角的值好計算, 例如計算右下角的值, 就是橫着豎着分別四個等差數列, 公差都爲2, 右下角那個的值爲, an=4n2+2na_n = 4n^2+2n, 所以每個點都用四個角去計算會容易一些。 暴力肯定不行, 10億, 一下就超時了, 所以每次直接走一條直線, 直接到拐角, 這樣只需要判斷在哪個區域即可, 用兩條直線的函數可以判斷座標的區域, 比較特殊的是四號區域, 因爲四號區域中有一個點是三號區域的(那個拐角), 所以應該特判一下。
在這裏插入圖片描述

#include <iostream>

using namespace std;

long long fun(long long x) {
	if(x < 0) return 0;
	return 4*x*x + 2*x;
}


int main()
{
	long long x, y;
	cin >> x >> y;
	//1號區域
	if(y >= -x && y > x) {
		cout << fun(y) - y*4 + (x + y);   //(x - (-y))
	}
	//2號區域
	else if(y <= x && y > -x) {
		cout << fun(x) - (y + x);   // y - (-x)	
	}
	//3號區域
	else if(x <= -y && x >= y) {
		cout << fun(-y) + (-y -x);
	}
	else {
		if(x +1 == y) {
			cout << fun(-y) + (-y)*2 +1;
		}
		else {
			cout << fun(-x-1) + (-x-1)*2 + 1 + (y - (x+1));
		}
	}

	return 0;
}


第八題 日誌統計

題目描述

小明維護着一個程序員論壇。現在他收集了一份"點贊"日誌,日誌共有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>
不能通過工程設置而省略常用頭文件。

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

題目分析

由於他給的數據不是按時間順序的,所以要先排序, 快排足以
  然後根據時間順序, 定兩個指針, 一個在前一個在後, 兩個指針中間的就是當前D時間內所有的點贊, 再開一個數組, 維護D時間內每個id被點讚的次數即可, 每次點讚的時候判斷是否超過了k, 超過了就標記一下曾經爲熱帖(又一個數組)。 最後遍歷一遍哪些被標記了即可。

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

using namespace std;

pair<int, int> ts[100005];
int cnt[100005];
bool hot[100005];

int main()
{
	int n, d, k;
	cin >> n >> d >> k;
	int x, y;
	for(int i=0; i<n; ++i)
	{
		cin >> ts[i].first >> ts[i].second;
		
	} 
	
	sort(ts, ts+n);
	
	int p = 0, q = 0;
	int cur;
	while(p < n)
	{
		while(p < n && ts[p].first - ts[q].first <= d) 
		{
			cur = ts[p].second;
			cnt[cur]++;
			if(cnt[cur] >= k) hot[cur] = true;
			p++;
		}
		while(q < p && ts[p].first - ts[q].first >= d)
		{
			cur = ts[q].second;
			cnt[cur]--;
			q++;
		}
	}
	
	for(int i=0; i<n; ++i)
		if(hot[i])
			cout << i << endl;
	
	return 0;
} 

第九題 全球變暖

題目描述

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

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

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

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

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

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

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

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

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

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

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

【輸出樣例】
1  



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

題目分析

先統計一次一開始有多少個島嶼, 每個島嶼用寬搜或者深搜都行, 找到一個島嶼計數加以,寬深搜淹沒整個島嶼, 然後還原, 統計一下每個像素會不會淹沒, 的出來狀態之後在用第一個方法統計一次多少個島嶼, 相減即可。

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>

using namespace std;

char mp[1005][1005];
char vmp[1005][1005]; 
typedef pair<int, int> P;
int dx[] = {0, 0, -1, 1}, dy[] = {1, -1, 0, 0};
int n;
void bfs(int x, int y)
{
	queue<P> que;
	for(que.push(P(x, y)); !que.empty(); que.pop())
	{
		P p = que.front();
		vmp[p.first][p.second] = '.';
		for(int i=0; i<4; ++i)
		{
			int xx = p.first + dx[i];
			int yy = p.second + dy[i];
			if(xx >= 0 && yy >= 0 && xx < n && yy < n && vmp[xx][yy] == '#')
				que.push(P(xx, yy));
		}
	}
}


int main()
{

	scanf("%d", &n);
	for(int i=0; i<n; ++i)
	{
		scanf("%s", mp[i]);
		strcpy(vmp[i], mp[i]);
	}
	int cnt1 = 0;
	for(int i=0; i<n; ++i)
		for(int j=0; j<n; ++j)
			if(vmp[i][j] == '#')
			{
				bfs(i, j);
				cnt1++;
			}
	for(int i=0; i<n; ++i)
		strcpy(vmp[i], mp[i]);
	for(int i=0; i<n; ++i)
		for(int j=0; j<n; ++j)
			if(vmp[i][j] == '#')
				for(int k=0; k<4; ++k)
					if(mp[i+dx[k]][j+dy[k]] == '.') 
					{
						vmp[i][j] = '.';
						break;
					}
	int cnt2 = 0;
	for(int i=0; i<n; ++i)
		for(int j=0; j<n; ++j)
			if(vmp[i][j] == '#')
			{
				bfs(i, j);
				cnt2++;
			}
	cout << cnt1 -cnt2 << endl;
	return 0;
} 

第十題 乘積最大

題目描述

給定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

題目分析

一看數據範圍, long long 沒跑了, 還是排序, 從大到小排序,然後維護兩個指針, 一個從左邊, 一個從右邊, 一次取兩個, 比較哪個大用哪個, 因爲可能兩個負數的乘積比兩個正數或者一正一負的大,也可能呢兩個數中有零, 所以要比較一下。
然後有個邊界需要特判一下, 就是當k是奇數的時候, 正好正數用完了, 這個時候就有幾種情況:
  1. 如果k == n, 那麼沒辦法, 只能是負數
   2. 如果左邊沒有正數, 那麼這個時候也只能是負數
   3. 如果左邊有正數, 那麼我就把這個正數拿出來, 用兩個負數代替這一正一負。
至於最後是0的情況, 上面已經包含了, 按負數處理即可。

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>

using namespace std;

#define ABS(x) (x > 0 ? x : -x)
#define MOD 1000000009
long long arr[100005];
int n, k;
bool cmp(long long& a, long long& b)
{
	return ABS(a) > ABS(b);
}

long long mult(long long a, long long b)
{
	a *= b;
	if(a < 0) a = -(-a % MOD);
	else a = a%MOD;
	return a;
}

int main()
{

	scanf("%d%d", &n, &k);
	for(int i=0; i<n; ++i)
		 scanf("%lld", &arr[i]);
	sort(arr, arr+n, greater<long long>());
	int p=0, q=n-1;
	int y = k % 2;
	if(y == 1) k--;
	long long ans = 1;
	while(p < q && k > 0)
	{
		if(mult(arr[p], arr[p+1] > mult(arr[q], arr[q-1])))
		{
			ans = mult(ans, mult(arr[p], arr[p+1]));
			p+=2;
		}
		else 
		{
			ans = mult(ans, mult(arr[q], arr[q-1]));
			q-=2;
		}
		k-=2;
	}
	if(y == 1) 
	{
		if(arr[p] <= 0) 
		{
			long long tmp = ans;
			int i =p;
			while(i >= 0 && arr[i] <= 0) i--;
			
			if(i < 0) ans = mult(ans, arr[p]);
			else 
			{
				tmp *= MOD;
				tmp /= arr[i];
				tmp = mult(tmp, arr[q]);
				tmp = mult(tmp, arr[q-1]);
				ans = ans > tmp ? ans : tmp;
			}
		}
		else ans = mult(ans, arr[p]);
	}
	
	cout << ans << endl;
	
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章