UVa 11538 Chess Queen(计数问题)

题目传送门

题意:给你一个n*m(n行m列)的棋盘,棋盘里有两个黑白旗子,当黑白旗子在同一行,同一列,同一对角线时处于攻击状态,问处于攻击状态时的种类数。

题解:根据题意可以将种类数分为三种类型:

一、当两种棋子处于同一列的情况:ans1=m*(m-1)*n;

二、当两种棋子处于同一行的情况:ans2=n*(n-1)*m;

三、当两种旗子处于对角线的情况:

这个直接看这个表格就可以很清晰的看出来

因为处在对角线的位置时,若其中一条对角线有k个格子,放置的种类肯定有k*(k-1);

因此只需要找有多少种长度的对角线的个数,并且求出其长度即可。

长度为m的对角线有n-m+1条,所以共有m*(m-1)*(n-m+1)种取法;

剩下的就是1+2*1+3*2+...+m*(m-1),这里我们用sum(i*(i-1))表示

sum(i*i-i)=sum(i*i)-sum(i)     (0<=i<m);

所以sum(i*(i-1))=∑i*(i-1) =m*(m+1)(2*m+1)/6-m*(m-1)/2;

因为有两边,所以还需要乘2

所以答案ans3=2*(2*∑i*(i-1) + (n-m+1)*m*(m-1)) (1 <= i <= m - 1)

ans3=2 * m * (m - 1) * (3 * n - m - 1) / 3;

所以ans=ans1+ans2+ans3;

!!!!!!!!!!!!!!有个重要前提就是n>m,否则的话公式中的n,m需要互换位置。

#include<iostream>
using namespace std;
long long n,m;
long long ans;
long long t;
int main()
{
    while(cin>>n>>m&&n&&m)
    {
        if(n<m)//互换位置
        {
            t=n;
            n=m;
            m=t;
        }
        ans=n*m*(m-1);
        ans+=m*n*(n-1);
        ans+=((n-m+1)*m*(m-1)+(m*(m-1)*(2*m-4)/3))*2;
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ytuyzh/article/details/83926582