题目:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28978
1. 两个皇后在同一行、同一列时候的情况很简单,其实就是n*C(m,2)+m*C(n,2)
2. 这道题可以通过一个3*5的方格矩形来找到对角线冲突的规律,我们都知道对角线共有两个方向:↖和↗
对于3*5的矩阵,只按一种方向的对角线的格子个数,会有如下规律:
1、2、3、3、3、2、1
总共有(5-3+1)个3,然后是两个升序的{1,2}
即,一个m*n且m<=n的矩阵,只按一种方向的对角线的格子个数满足:
1,2,3,... , m, m, ..., m, m-1, m-2, ... , 2, 1
总共有n-m+1个m,其余为2两个升序的{1,2,... ,m-1}
所以,其实这道题是有解析解的!
对角线的冲突个数=2*[2*∑i=1~m-1 i*(i-1) + (n-m+1)*m*(m-1)]=2n(n-1)(3m-n-1)/3
但是,也可以偷个懒,不推导公式,而是直接通过序列特性用循环计算最后结果。
最后注意,虽说题目说不会超过long long,但是我用下面的代码好像会WA,但是改为unsigned long long就AC了。囧~
但好像直接用公式就没事~~~唉,为了稳如poi,还是用unsigned long long吧~
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; int main () { unsigned long long ans, m, n; while(scanf("%llu%llu", &m, &n) && (m|n)) { if(m > n) swap(m, n); ans = m*n*(n-1LL) + n*m*(m-1LL); for(int i=2; i<=n; i++) { if(i<m) ans += 4LL*i*(i-1); else ans += 2LL*m*(m-1); } printf("%llu\n", ans); } return 0; }
直接用公式得到解析解:
#include<iostream> #include<algorithm> using namespace std; int main() { long long n,m; while(cin>>n>>m && n+m) { if(n>m) swap(n,m); cout<<n*m*(m+n-2)+2*n*(n-1)*(3*m-n-1)/3<<endl; } return 0; }