UVA 11538 Chess Queen

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
/*
题意:棋盘n*m,问你有多少种放置两个相互攻击的皇后

先比较m和n值,若m>n,两者交换一下,即保证m<=n
分两种情况讨论:
1.两个皇后在同一直线上:
    选定好一个皇后A,它可以摆放的位置有n*m种,由于两个皇后在同一直线上,另一个B只能摆放在(n-1+m-1)个位置。
    所以总的种类为:n*m*(n+m-2),注意:这里不用再乘以二,因为我们先摆放A再摆放B的方案数其实已经包含了先摆放B再摆放A的方案数。

2.两个皇后在同一斜线上:
    这种情况,两个皇后只能在一个i*i大小的正方形的两个对角线的两端,可以有四种摆放。(2<=i<=min(n,m)=m)
    接下来,就枚举对应于某个值i,n*m的棋盘中有多少不同的i*i的方格,方案数为f(i)=(n-i+1)*(m-i+1)
    展开来,再对不同的次数对应累加,得出sum=f(2)+f(3)+...+f(m)=4*((m-1)*n*m-m*(m-1)/2*n-m*(m-1)/2*m+(m-1)*m*(2*m-1)/6)

答案即为两者的和。

白书上求对角线的方案数的方法:
不妨设n<=m,所有/向对角线,从左到右的长度依次为:
    1 2 3 ... n-1 n n ... n(m-n+1个n) n-1 ... 3 2 1
在长度为l的对角线上,摆放的方案数为l*(l-1)。
考虑到还有\向的对角线,所以还要乘以2。
所以总的方案数为:
    2*(sum{i*(i-1),2<=i<=n-1}+(m-n+1)*n*(n-1));
*/
using namespace std;

int main()
{
    long long n,m;
    while(scanf("%lld%lld",&n,&m)!=EOF){
        if(n==0 && m==0)
            break;
        if(n==0 || m==0)
            printf("0\n");
        if(m>n)
            swap(n,m);
//printf("%lld  %lld\n",n,m);
        long long ans;
        ans=n*m*(n+m-2)+4*((m-1)*n*m-m*(m-1)/2*n-m*(m-1)/2*m+(m-1)*m*(2*m-1)/6);
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2013-10-30 09:28  辰曦~文若  阅读(185)  评论(0编辑  收藏  举报