点此看题面

大致题意: 问一张\(n\times m\)的网格图上格点三角形数目。

前言

看到网格图就要想到分治。by 【BZOJ4456】[ZJOI2016] 旅行者

做了几乎一天的类欧几里得题目,现在找道水题放松一下心情。

容斥

显然可以考虑容斥吧。

选出三个点总方案数为\(C_{n\times m}^3\),然后减去三点共线的情况数即为答案。

而三点共线可以分成在同一行上,同一列上,或是一条斜线上。

在同一行上的方案数显然是\(n\times C_m^3\),同一列上显然是\(m\times C_n^3\),而斜线要稍微有技巧一点。

考虑我们枚举左右两点横纵坐标差值\(i,j\),令\(g=gcd(i,j)\),则中间的点必然只有\(g-1\)种选择(因为必须要取格点),而选出这样一对点的方案数又有\((n-i)\times(m-j)\)种。

不过由于斜线既可以斜着向上,也可以斜着向下,因此方案数还要乘\(2\)

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000
#define LL long long
#define C(x) (1LL*(x)*((x)-1)*((x)-2)/6)//求C(x,3)
using namespace std;
int n,m;I int gcd(CI x,CI y) {return y?gcd(y,x%y):x;}//求gcd
int main()
{
	scanf("%d%d",&n,&m),++n,++m;LL ans=C(n*m)-1LL*n*C(m)-1LL*m*C(n);//容斥
	RI i,j;for(i=1;i<=n;++i) for(j=1;j<=m;++j) ans-=2LL*(gcd(i,j)-1)*(n-i)*(m-j);//减去斜线情况
	return printf("%lld\n",ans),0;
}

相关文章:

  • 2022-12-23
  • 2022-02-07
  • 2021-07-21
  • 2021-12-30
  • 2021-08-22
  • 2021-12-15
  • 2021-07-18
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-03-04
  • 2022-01-17
  • 2021-11-16
  • 2022-01-27
  • 2022-12-23
相关资源
相似解决方案