bzoj3505【CQOI2014】数三角形

3505: [Cqoi2014]数三角形

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 1036   Solved: 636
[ Submit][ Status][ Discuss]

Description

给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个。下图为4x4的网格上的一个三角形。

注意三角形的三点不能共线。

Input

输入一行,包含两个空格分隔的正整数m和n。

Output


输出一个正整数,为所求三角形数量。

Sample Input


2 2

Sample Output

76


数据范围
1<=m,n<=1000



直接求不好求,运用补集思想,转化成求三点共线的数量。

水平和竖直共线,直接用组合数求出。倾斜的枚举两边点的相对位置,再用最大公约数求解。




#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
ll n,m,ans;
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}
int main()
{
	n=read()+1;m=read()+1;
	ans=(n*m)*(n*m-1)*(n*m-2)/6;
	if (n>=3) ans-=n*(n-1)*(n-2)/6*m;
	if (m>=3) ans-=m*(m-1)*(m-2)/6*n;
	F(i,1,n-1) F(j,1,m-1)
	{
		int tmp=gcd(i,j)+1;
		ans-=(n-i)*(m-j)*(tmp-2)*2;
	}
	printf("%lld\n",ans);
	return 0;
}


你可能感兴趣的:(bzoj)