ZOJ 3647 Gao the Grid dp,思路,格中取同一行的三点,经典 难度:3

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4837

三角形的总数=格子中任取3个点的组合数-同一横行任取3个点数目-同一纵行任取3个点数目-同一斜直线上任取3个点数目

同一横行和同一纵行都好求

同一斜行的距离最远的点必然是一个矩形的两个端点,设矩形的长宽为l,w,中间可以取的点数则是(gcd(l,w)-1),左上角或左下角的起点反而不重要.

能够取到该矩形的可能是 (n-l+1)*(m-w+1),因为左上角作为起点或左下角作为起点都可以,所以斜行的情况是sigma((gcd(l,w)-1)*(n-l+1)*(m-w+1)*2)

比赛时虽然考虑到了矩形但是没有想到让两个端点恰好成为最远的点而是分类统计,最终因为不够精细卡题

#include <cstdio>
#include <iostream>
#include <cstring>
#define clr(x,y) memset(x, y, sizeof x)
#include <cmath>
using namespace std;

typedef long long LL;

LL n, m;

LL cal(LL x)
{
    if (x < 3) return 0;
    return x * (x - 1) * (x - 2) / 6;
}

LL gcd(LL a,LL b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}
int main()
{
    while(scanf("%lld%lld", &n, &m) != EOF)
    {
        LL ans = cal((n +1) * (m + 1)) - (m + 1) * cal(n+1) - (n + 1) * cal(m + 1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
				ans-=2*(gcd(i,j)-1)*(n-i+1)*(m-j+1);

            }
        }
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xuesu/p/4509024.html