题意:给你一个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;
}