UVa11538

来源:互联网 发布:网络视频歌曲大全 编辑:程序博客网 时间:2024/06/17 23:59

题目链接

简介:
在一个n*m的方格中放置两个不同的皇后,使得两者可以互相攻击

分析:
因为只有两个皇后,因此互相攻击分方法只有在同一行,在同一列,在同一对角线上
这三种情况没有交集,所以可以分别求出后,运用加法原理统计方案

设A(n,m)为同一行放置两个皇后的方案数,
B(n,m)为同一列放置两个皇后的方案数,
C(n,m)为同一对角线放置两个皇后的方案数

  • A(n,m)
    我们先选一行(n种选择)
    在m个位置中选择两个位置(全排列:m*(m-1))
    方案数:n*m*(m-1)

  • B(n,m)
    实际上就是A(m,n)
    方案数:m*n*(n-1)

  • C(n,m)
    对角线的方案会有一点难度,不妨设n<=m,则所有/向的对角线长度为:

    1 , 2 , 3 ,…, n , n , n ,…, n , n-1 , n-2 ,…, 3 , 2 , 1

    其中有(m-n+1)个n
    这里写图片描述
    考虑还有另一个方向的对角线,结果还要乘以2:
    这里写图片描述

    其中这里写图片描述

    因此这里写图片描述

tip

以前从来没有进行过算术运算分析,
在解决计数问题时一定要考虑算数运算溢出
我们用64位无符号长整型保存n,m,最大可以保存2^64-1>1.8*10^19
则上述的所有乘法运算结果都不会溢出

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#define ll unsigned long longusing namespace std;int main(){    ll n,m;    while (scanf("%lld%lld",&n,&m)!=EOF&&n)    {        if (n>m) swap(n,m);        ll ans=m*n*(n-1);        ans+=n*m*(m-1);        ans+=2*n*(n-1)*(3*m-n-1)/3;        cout<<ans<<endl;    }    return 0;}
原创粉丝点击