P3166

题目链接

P3166

题意

求在网格上,三点都在格点上的三角形个数。

思路

看到题面,觉得正着想有点难,考虑用整体减去不满足的就是答案。

在网格里选三个点,方案数是 C ( n + 1 ) ( m + 1 ) 3 \text{C}_{(n+1)(m+1)}^{3} C(n+1)(m+1)3

三点共线的情况还可以分成三种:

1. 1. 1. 横着三点共线。

2. 2. 2. 竖着三点共线。

3. 3. 3. 斜着三点共线。

前两种都可以直接考虑,以第一种为例,在 n + 1 n+1 n+1 行里选三个点,有 m + 1 m+1 m+1 列,所以方案数是 C n + 1 3 × ( m + 1 ) \text{C}_{n+1}^{3} \times (m+1) Cn+13×(m+1) 种。第二种同理,方案数是 C m + 1 3 × ( n + 1 ) \text{C}_{m+1}^{3} \times (n+1) Cm+13×(n+1) 种。

考虑第三种,先选择两点 ( 0 , 0 ) (0,0) (0,0) 以及 ( i , j ) (i,j) (i,j),这条直线解析式为 y = j i x y=\frac{j}{i}x y=ijx。要想坐标为整数,就要 j j j 能整除 i i i,所以 j j j i i i 互质时肯定不行。

g c d ( i , j ) = d gcd(i,j)=d gcd(i,j)=d,那么解析式变为 y = j / d i / d x y=\frac{j/d}{i/d}x y=i/dj/dx。那么只要 i / d ∣ x i/d|x i/dx 就可以了。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
inline int read(){
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}
inline void write(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
const int maxn=1e3+5;
int n,m,x,y,ans;
signed main(){
	x=read(),y=read(),n=x+1,m=y+1;
	ans=(n*m)*(n*m-1)*(n*m-2)/6-m*n*(n-1)*(n-2)/6-n*m*(m-1)*(m-2)/6;
	for(int i=1;i<n;i++) for(int j=1;j<m;j++) ans-=2*(__gcd(i,j)-1)*(n-i)*(m-j);
	cout<<ans<<endl;
	return 0;
}

提交记录

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值