1. 程式人生 > >Codeforces Round #511 (Div. 2) D. Little C Loves 3 II

Codeforces Round #511 (Div. 2) D. Little C Loves 3 II

codeforces上的一道題,AC程式碼貼在最後面

目錄

1.猜想

2.嘗試

1.猜想

容易得出一個 n * m 的棋盤,有以下結論:

(1) 如果 n * m 為偶數,棋盤最多能放 n * m 個棋子;

(2) 如果 n * m 為奇數,棋盤最多能放 n * (m - 1) 個棋子。

那麼我們猜想當 n 和 m 足夠大的時候,符合題意的棋子數是不是總能達到這個最大值?

2.嘗試

從簡單的情況開始嘗試找規律,不妨設 n ≤ m,從 n = 1 開始找規律。其中能填滿棋盤的情況會用紅色標註。

① n = 1

m = 1:結果為0

m = 2:結果為0

m = 3:結果為0

m = 4:結果為2

m = 5:結果為4

m = 6:結果為6,能填滿整個棋盤

所以 n = 1 的情況可以以 6 為週期來分析,當且僅當 m % 6 == 0 的時候,可以填滿整個棋盤

對於剩餘的情況,我們可以構造一個數組 ka[6] = {0, 0, 0, 0, 2, 4},那麼最多可符合題意的棋子數量 = (m / 6) * 6 + ka[m % 6]。

② n = 2

m = 2:結果為 0

m = 3:結果為 4

m = 4:結果為 8,能填滿

m = 5:結果為 10,能填滿

m = 6:結果為 12,能填滿

容易得出,任何一個大於等於 8 的偶數 eve 都能表示成 eve = 4 * a + 6 * b 的形式,所以當 m 為偶數時(m ≥ 4),能填滿棋盤

而任何一個大於等於 8 的奇數 odd 總能表示成 odd = 5 * a + 4 * b + 6 * c(用歸納法很容易證明),所以當 m 為奇數時(m > 8),能填滿棋盤

現在還剩 m = 7 的情況沒有考慮,因為用4,5,6三個自然數沒辦法構造出7,當 m = 7 時,結果為 12,不能填滿。

所以總結一下 n = 2 的結論

當 m = 2、m = 3、m = 7 時無法填滿,是特殊情況;

其 m 不為 2 或 3 或 7 時,無論奇數還是偶數,均可填滿棋盤,達到最大值 n * m。

③ n = 3

m = 3 :結果為 8,剛好達到 n * m - 1 這個最大值

m = 4 :結果為 12,能填滿

m = 6 :結果為 18,能填滿

由於“任何大於等於 8 的偶數都可以用 4 和 6 構造出來”,所以當 m 為偶數時(m ≥ 4),能填滿棋盤

而當 m 為奇數時,可以把棋盤拆成一個 n * (m - 3) 和 n * 3 的棋盤(n = 3),

對於 n * (m - 3) 的棋盤,由於 m - 3 一定是大於等於 2 的偶數,所以結合②的結論,能填滿

對於 n * 3 的棋盤,恰好差一個棋格沒法填,

因此 當 m 為奇數時,雖然不能填滿,但是能達到 n * m - 1 這個最大可容納棋子數。

總結一下 n = 3的結論

若 m 為偶數,能填滿棋盤;

若 m 為奇數,恰好有一個棋格多餘,能達到奇數棋盤的最大值 n * m - 1。

④ n = 4

先取消掉 n < m 的假設,

m = 2 :結果為 8,能填滿

m = 3 :結果為 12,能填滿

由於 m = 2 的時候能填滿,所以當 m 為偶數時,一定能填滿

若 m 為奇數,同樣可以拆分成 n * (m - 3) 和 n * 3的棋盤,

n * (m - 3) 的棋盤即 n = 4,m` 為偶數的棋盤,一定能填滿,

4 * 3 的棋盤也能填滿,所以當 m 為奇數時,也一定能填滿

結論:

無論 m 為奇數或是偶數,一定都能填滿,達到最大值 n * m

⑤ n = 5

先取消掉 n < m 的假設,

m = 2 :結果為 10,能填滿

m = 3 :結果為 15,能填滿

與④中的推理方法類似,拆成 n * (m - 3) 和 n * 3 的棋盤可以得出如下結論

若 m 為偶數,一定能填滿

若 m 為奇數,雖然不能填滿,但是能達到最大值 n * m - 1。

⑥ n = 6

由於①中說過 1 * 6 的棋盤是可以填滿的,所以無論 m 為奇數還是偶數,總能填滿

3.得出結論

下面對 n,m > 6 的情況做分析。

還是以1.猜想中的猜想為基準,分成三種情況:n 和 m 都是偶數、n 和 m 都是奇數、n 和 m 一個為奇數,一個為偶數。

A. n 和 m 都是偶數

結合第2部分②④⑥中 m 為偶數時的結論,得出此情況一定能填滿棋盤

B. n 和 m 一個為奇數,一個為偶數

不妨設 m 是其中的奇數。

還是拆分成 n * (m - 3) 和 n * 3 兩個棋盤,

n * (m - 3) 棋盤就是A中“兩個都是偶數”的棋盤,所以能填滿,

n * 3 棋盤對應的是2的③中"n = 3,m 為偶數"的棋盤,也能填滿。

所以此情況一定能填滿棋盤

C. n 和 m 都是奇數

還是用拆分的方法,拆成 n * (m - 3) 和 n * 3 兩個棋盤,

n * (m - 3) 棋盤就是B中“一個是奇數一個是偶數”的棋盤,所以能填滿,

n * 3 棋盤對應的是2的③中“n = 3, m 為奇數”的棋盤,不能填滿,剛好空一個棋格,所以能達到奇數棋盤的最大值 n * m - 1,

所以此情況的最大容納棋子數量為 n * m - 1。

結合本小節A、B、C和第二小節①②③④⑤⑥的結論,可以得出最終結論如下:

if (n == 1)
    按照①單獨分析;
else if (n == 2)
    按照②單獨分析,注意 m = 7 的情況;
else if (n * m 為偶數)
    結果是 n * m;
else // n * m 均為奇數
    結果是 n * m - 1;

4.程式碼

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <bitset>
#include <cmath>
#include <bitset>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <stack>
#include <queue>
#include <functional>
#include <time.h>
#include <cstring>
#include <complex>
#include <stdio.h>
#include <iomanip>
#include <fstream>
#include <list>
#include <numeric>
#include <random>
#include <memory>

using namespace std;

#define MAXN 3e5 + 10
#define MAXNUM 1.5e7 + 10

const long ka[6] = { 0, 0, 0, 0, 2, 4 };

int main()
{
	long long n, m;
	while(cin >> n >> m)
	{
		if (n > m)
		{
			int tmp = n; n = m; m = tmp;
		}
		long long ret;
		if (n == 1) ret = m / 6 * 6 + ka[m % 6];
		else if (n == 2)
		{
			if (m == 2) ret = 0;
			else if (m == 3) ret = 4;
			else if (m == 7) ret = 12;
			else ret = n * m;
		}
		else {
			if (n % 2 && m % 2) ret = n * m - 1;
			else ret = n * m;
		}

		cout << ret << endl;
	}

	return 0;
}