Chess Queen UVA - 11538 象棋中的皇后 排列組合問題

在2x2 棋盤上放兩個相互攻擊的皇后( 一白一黑) , 一共有12 種方法,如圖2-1 所示。
圖2 -1
如果棋盤是nXm 的,有多少種方法放置兩個相互攻擊的皇后?例如n=1 00, m=223 時答案爲10 907 100 。
【輸入格式】
輸入由不超過5000 行組成,每行均爲-組數據,包含兩個整數n, m (0 運n,m~二10勺。輸入結束標誌爲n=m=O 。
【輸出格式】
對於每組數據,輸出在nXm 棋盤上放兩個相互攻擊的皇后的方案數。輸出保證不超過64 位帶符號整數的範圍。
【分析】
因爲只有兩個皇后,因此相互攻擊的方式只有兩個皇后在同一行、同一列或同一對角線3 種情況。這3 種情況沒有交集,因此可以用加法原理。設在同一行放兩個皇后的方案數爲A(n,m) ,同一列放兩個皇后的方案數爲B(n ,時,同一對角線放兩個皇后的方案數爲D(n ,m) ,則答案爲A(n ,m)+B(n,m)+D(n ,m) 。

A(n ,m)的計算可以用乘法原理:放自後有nm 種方法,放黑後有m-l 種方法,相乘就是nm(m-1) 。也可以理解爲先選一行(有n 種方法) ,然後在這一行中選兩個位置做全排列,因此有m(m-1)種方案。根據乘法原理得到nm(m-1) 。
B(n ,m)其實就等於A(m,n) ( 想一想,爲什麼) , 也就是mn(n-1) 。

求D(n ,m)的思考過程會稍微麻煩一些。不妨設n運m , 所有/向的對角線,從左到右的長度依次爲   

                                    
考慮到還有另一個方向的對角線,上面的整個結果還要乘以2 ,即

                 
程序如下。 

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

int main(int argc, char** argv) {
	unsigned long long n, m; // 最大可以保存2^64-1>1.8*10^19
	while( cin>> n>> m && (n || m)){
		if(n > m) swap(n,m); // 這樣就避免了對n<=m和n>m兩種情況分類討論
		cout<< n*m*(m-1) + m*n*(n-1) + 2*n*(n-1)*(3*m-n-1)/3 << "\n";
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章