Codeforces Round #511 (Div. 2) D. Little C Loves 3 II
codeforces上的一道題,AC程式碼貼在最後面
目錄
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;
}