[CQOI2014]数三角形 数论

本文探讨了在nxm网格中计算所有不共线格点构成的三角形数量的方法。通过排除三点共线的情况,利用组合数学原理和最大公约数算法,给出了一个高效的计算公式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


Sample Input
2 2


Sample Output
76


我们首先可知不管三点一线的答案有C(n,3)种。
然后横着的直线跟竖着的支线很好搞出来。
然后考虑斜着的直线,对于两个点,
设差值为x,y,形成的直线上面会有gcd(x,y)-1个整点,
这个线段能平移的往上范围是n-x+1,往右平移的范围是m-y+1。
那么你还可以反转,于是共有(n-x+1) * (m-y+1) * 2 * (gcd(x,y)-1)种。


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
int read() {
	int s = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
	return s * f;
}

LL f[1100][1100];

LL gcd(LL a, LL b) {
	if(b == 0) return a;
	return gcd(b, a % b);
}

LL get(LL x) {return x * (x - 1) * (x - 2) / 6;}

int main() {
	LL n = read(), m = read(); n++, m++;
	LL ans = get(n * m) - (LL)get(n) * m - (LL)get(m) * n;
	for(LL i = 1; i < n; i++) {
		for(LL j = 1; j < m; j++) {
			LL k = gcd(i, j) - 1;
			ans -= (LL)k * (n - i) * (m - j) * 2LL;
		}
	} printf("%lld\n", ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值