今天遇到了一道组合问题,题目描述如下。
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4837
题意:给定一个的矩阵,在这个矩阵中任意选取3点,能构成多少个三角形?
分析:这个题明显是一个组合问题,利用容斥的思想。在的矩阵中一共有个点,那么有种
选择,在这种选择中三点共线的情况是不合法的,不合法主要分两种情况。
(1)处于同一斜线上
枚举的矩形,那么对角线上的两点已经固定,在这两点中间选一个点即可,我们知道,给定两个整
数端点和,直线上的整点个数为,减去已经固定的两
个,中间还有个整点,然后的矩形还可以移动,一共有
种情况,而每一个矩形有两个对角线,所以还要乘以2。
(2)处于同一竖直线或者水平线上
这种情况容易一点在每一个竖直线上选择3点,且每一列都是这样共有种情况。
同理,还有。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b)
{
return b ? gcd(b,a%b):a;
}
LL num(LL n,LL m)
{
LL ans = 0;
for(int i=2;i<=n;i++)
{
for(int j=2;j<=m;j++)
ans += (gcd(i,j) - 1) * (n - i + 1) * (m - j + 1) * 2;
}
return ans;
}
LL Work(LL n,LL m)
{
LL t = (n + 1) * (m + 1);
LL ans = t * (t - 1) * (t - 2) / 6;
ans -= num(n,m);
ans -= n * (n * n - 1) * (m + 1) / 6;
ans -= m * (m * m - 1) * (n + 1) / 6;
return ans;
}
int main()
{
LL n,m;
while(scanf("%lld%lld",&n,&m)!=EOF)
printf("%lld\n",Work(n,m));
return 0;
}