【bzoj3505】[Cqoi2014]数三角形 容斥原理

题目描述

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

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

输入

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

输出

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

样例输入

2 2

样例输出

76



题解

容斥原理

三角形数目=选出三个点的方案数-三点共线的方案数。

选出三个点的方案数显然为$C_{(n+1)(m+1)}^3$。

三线共线的方案数,考虑枚举两端点,统计出一个矩形内的方案数,再算出总体方案数。其中点坐标的gcd-1为中间点的个数。

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll gcd(ll a , ll b)
{
	return b ? gcd(b , a % b) : a;
}
int main()
{
	ll n , m , i , j , t , ans;
	scanf("%lld%lld" , &n , &m) , t = (n + 1) * (m + 1);
	ans = t * (t - 1) * (t - 2) / 6;
	for(i = 0 ; i <= n ; i ++ )
	{
		for(j = 0 ; j <= m ; j ++ )
		{
			t = gcd(i , j) - 1;
			if(t <= 0) continue;
			t *= (n - i + 1) * (m - j + 1);
			if(i && j) ans -= t << 1;
			else ans -= t;
		}
	}
	printf("%lld\n" , ans);
	return 0;
}
时间: 2024-10-07 15:09:14

【bzoj3505】[Cqoi2014]数三角形 容斥原理的相关文章

bzoj3505: [Cqoi2014]数三角形 [数论][gcd]

Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和n. Output 输出一个正整数,为所求三角形数量. Sample Input 2 2 Sample Output 76 数据范围 1<=m,n<=1000 太伤心了..不能abs(int)??? 首先格点个数是(n+1)*(m+1)的,所以我们先把n和m都+1. 先选出三个不同点,方案数是C(

[bzoj3505 Cqoi2014] 数三角形 (容斥+数学)

传送门 Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和n. Output 输出一个正整数,为所求三角形数量. Sample Input 2 2 Sample Output 76 HINT 1<=m,n<=1000 Solution 首先思路肯定是随意三个点方案-三点共线方案 随意三个点方案随意求 主要求三点共线: 有个神奇的结论:节点坐标gc

【排列组合】bzoj3505 [Cqoi2014]数三角形

http://blog.csdn.net/zhb1997/article/details/38474795 #include<cstdio> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; int n,m; ll ans; int main() { // freopen("bzoj3505.in","r",stdin

bzoj3505 [Cqoi2014]数三角形

题目链接 先算在n*m个点中任选3个的方案数,再减去三点共线的方案数 我为什么要做这种水题?因为我很弱 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include<cmath> 8 #include<ctime>

【BZOJ 3505】 [Cqoi2014]数三角形 容斥原理+排列组合+GCD

我们先把所有三角形用排列组合算出来,再把一行一列上的三点共线减去,然后我们只观察向右上的三点共线,向左上的乘二即可,我们发现我们如果枚举所有的两边点再乘中间点的个数(GCD),那么我们发现所有的两边点都会形成一个矩形对角线,而且他们的形状一定则贡献一定那么我们可以枚举形状来求贡献和. #include <cstdio> typedef long long LL; LL n,m,ans,N,M; LL GCD(LL x,LL y){ return x==0?y:GCD(y%x,x); } int

bzoj 3505 [Cqoi2014]数三角形 容斥原理+数学

题面 题目传送门 解法 直接求三角形个数似乎并不好求 那么我们不妨考虑补集转化,即\(ans={nm\choose3}\)-三点共线的个数 三点共线分别为在行上,在列上,以及斜着的 斜着的只要枚举斜率是什么,然后就很好求了 代码 #include <bits/stdc++.h> #define int long long using namespace std; template <typename node> void read(node &x) { x = 0; int

【BZOJ3505】[Cqoi2014]数三角形 组合数

[BZOJ3505][Cqoi2014]数三角形 Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和n. Output 输出一个正整数,为所求三角形数量. Sample Input 2 2 Sample Output 76 数据范围 1<=m,n<=1000 题解:显然要用补集法,我们只需要求出三点共线的方案数即可.方法是先枚举两端的点所形成的向

bzoj3505 / P3166 [CQOI2014]数三角形

P3166 [CQOI2014]数三角形 前置知识:某两个点$(x_{1},,y_{1}),(x_{2},y_{2})\quad (x_{1}<x_{2},y_{1}<y_{2})$所连成的线段穿过整点的个数为$gcd(x_{2}-x_{1},y_{2}-y_{1})-1$ “注意三角形的三点不能共线.” 暗示你可以处理出总方案再减去三点共线的方案. 显然,总方案就是在$(n+1)*(m+1)$个点中任选$3$个.于是$tot=C((n+1)*(m+1),3)$ 现在我们要算出三点共线的方案

BZOJ 3505: [Cqoi2014]数三角形( 组合数 )

先n++, m++ 显然答案就是C(3, n*m) - m*C(3, n) - n*C(3, m) - cnt. 表示在全部点中选出3个的方案减去不合法的, 同一行/列的不合法方案很好求, 对角线的不合法方案cnt比较麻烦. 枚举对角线(左下-右上), 即(0, 0)-(x, y), 我们发现这种情况有(n-y)*(m-x)*2(算上左上-右下的)种, 然后中间有gcd(x, y)-1个点(不合法), 乘起来就好了. ---------------------------------------