【CQOI2014】数三角形
2018-01-08 20:02
148 查看
这是一道比较有意思也有意义的题目~
![](https://img-blog.csdn.net/20180108191827223?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2R5MTIwNjQ3MzYwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1 1
输入2:
2 2
4
输出2:
76
对于100%的数据 1<=m,n<=1000
很容易想到直接用容斥原理。
首先算出在这(n+1)*(m+1)个点中,任选三个的方案数,很明显是Sum=C(p,3)[p=(n+1)∗(m+1)]。
但是我们发现在这Sum个数中,有的是三个点连成一条线的,是无法组成一个三角形的,那么我们就要看看可连成一条线的方案数为多少。首先平行于坐标轴的这些线段我们是不用讲的。
我们考虑:确定两个整点(x1,y1),(x2,y2),它们连成的线上拥有的整点数为gcd(x2−x1,y2−y1)+1(包括这两点)
这样必须含有这两点时,在这条线上三个点的方案数就是
gcd(x2−x1,y2−y1)+1[待会会予以证明]
![](https://img-blog.csdn.net/20180108193147581?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2R5MTIwNjQ3MzYwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
但是我们明显不能枚举两个点,然后我们就可以发现其实只用枚举这个矩阵的长和宽,从而确定对角线。
那么对于一个长和宽分别为i,j的矩阵来说,对角线在整个大矩阵的个数为(n-i)*(m-j);
![](https://img-blog.csdn.net/20180108194115898?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2R5MTIwNjQ3MzYwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
也就是我们枚举i,j,然后ans−=[gcd(i,j)−1]∗(n−i)∗(n−j)∗2.
因为矩形的对角线有两条,所以要*2.
下面我们来证明为什么数量为gcd(i,j)
![](https://img-blog.csdn.net/20180108195147941?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2R5MTIwNjQ3MzYwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
那么拥有的点就是两个,一个是(2,3),一个是(4,6)。
我们可以由斜率相等知道,在这上面的点横纵坐标都可以整除gcd(6,9),
那么第一个点就是(6gcd(6,9),9gcd(6,9))=(2,3),然后从特殊到一般就是(igcd(i,j),jgcd(i,j)).
然后每次加上(igcd(i,j),jgcd(i,j)),直到等于(i,j)为止,
像例子中:(2,3)->(4,6)->(6,9)
那么有多少个呢?就是i/igcd(i,j)或j/jgcd(i,j)那个就是gcd(i,j)个,因为有一个是枚举出来的,所以总个数就是gcd(i,j)−1个.
Description
Input
输入一行,包含两个空格分隔的正整数m和n。Output
输出一个正整数,为所求三角形数量。Sample Input
输入1:1 1
输入2:
2 2
Sample Output
输出1:4
输出2:
76
Data Constraint
对于30%的数据 1<=m,n<=10对于100%的数据 1<=m,n<=1000
Solution
我们需要仔细思考。很容易想到直接用容斥原理。
首先算出在这(n+1)*(m+1)个点中,任选三个的方案数,很明显是Sum=C(p,3)[p=(n+1)∗(m+1)]。
但是我们发现在这Sum个数中,有的是三个点连成一条线的,是无法组成一个三角形的,那么我们就要看看可连成一条线的方案数为多少。首先平行于坐标轴的这些线段我们是不用讲的。
我们考虑:确定两个整点(x1,y1),(x2,y2),它们连成的线上拥有的整点数为gcd(x2−x1,y2−y1)+1(包括这两点)
这样必须含有这两点时,在这条线上三个点的方案数就是
gcd(x2−x1,y2−y1)+1[待会会予以证明]
但是我们明显不能枚举两个点,然后我们就可以发现其实只用枚举这个矩阵的长和宽,从而确定对角线。
那么对于一个长和宽分别为i,j的矩阵来说,对角线在整个大矩阵的个数为(n-i)*(m-j);
也就是我们枚举i,j,然后ans−=[gcd(i,j)−1]∗(n−i)∗(n−j)∗2.
因为矩形的对角线有两条,所以要*2.
下面我们来证明为什么数量为gcd(i,j)
For example
我们假设一点为(6,9)那么拥有的点就是两个,一个是(2,3),一个是(4,6)。
我们可以由斜率相等知道,在这上面的点横纵坐标都可以整除gcd(6,9),
那么第一个点就是(6gcd(6,9),9gcd(6,9))=(2,3),然后从特殊到一般就是(igcd(i,j),jgcd(i,j)).
然后每次加上(igcd(i,j),jgcd(i,j)),直到等于(i,j)为止,
像例子中:(2,3)->(4,6)->(6,9)
那么有多少个呢?就是i/igcd(i,j)或j/jgcd(i,j)那个就是gcd(i,j)个,因为有一个是枚举出来的,所以总个数就是gcd(i,j)−1个.
#include<cstdio> #include<iostream> using namespace std; long long n,m,p; long long ans; long long gcd(long long x,long long y) { if(x%y==0) return y; else return gcd(y,x%y); } int main() { scanf("%lld%lld",&n,&m); long long i,j,k,l;p=(n+1)*(m+1); ans=p*(p-1)*(p-2)/6-(m+1)*(n+1)*n*(n-1)/6-(n+1)*(m+1)*m*(m-1)/6; for (i=1;i<=n;++i) for (j=1;j<=m;j++) ans-=2*(n-i+1)*(m-j+1)*(gcd(i,j)-1); printf("%lld\n",ans); }
相关文章推荐
- [CQOI2014]数三角形
- BZOJ3505 [Cqoi2014]数三角形 数学
- 【组合】BZOJ3505(Cqoi2014)[数三角形]题解
- bzoj3505【CQOI2014】数三角形
- bzoj3505: [Cqoi2014]数三角形
- 3505: [Cqoi2014]数三角形 组合数学
- bzoj3505 [Cqoi2014]数三角形
- BZOJ-3505-数三角形-CQOI2014
- 【bzoj3505】[Cqoi2014]数三角形
- bzoj3505: [Cqoi2014]数三角形
- 【BZOJ 3505】 [Cqoi2014]数三角形 容斥原理+排列组合+GCD
- BZOJ-3505-数三角形-CQOI2014
- BZOJ 3505 CQOI2014 数三角形 组合数学
- 【bzoj 3505】: [Cqoi2014]数三角形
- BZOJ3505: [Cqoi2014]数三角形 解题报告
- 【CQOI2014】【BZOJ3505】数三角形
- [Bzoj3505][Cqoi2014]数三角形
- BZOJ 3505 CQOI 2014 数三角形 数学
- bzoj3505 [Cqoi2014]数三角形 题解
- [组合计数] BZOJ 3505 [Cqoi2014]数三角形