BZOJ3505: [Cqoi2014]数三角形 解题报告

来源:互联网 发布:js array 删除 编辑:程序博客网 时间:2024/05/21 15:44

本来不难的一题,发现我不会算两点线段间整点数…..
这道题可以转化一下,求出所有三角形数量,减去三点共线的三角形数
求三点共线的三角形数的话,枚举n,m得到一个线段,以(1,1),(n,m)为三角形的两个顶点,1*剩余线段上的点就是这个线段的贡献,再乘上共有多少个贡献相同的线段(对于一条线段(1,1),(n,m)(n,1),(1,m)和他也是相同的)
怎么求线段间整点数呢?
这里写图片描述
这是一条线段,横着看有x个间隔,竖着看有y个间隔,那么从(0,0)沿线段走,x改变了ay就改变了ayx,要使得这是个整点,ayx需要是整数,所以a能取的值是kxgcd(x,y)所以整点数是xxgcd(x,y)+1,即gcd(x,y)+1




code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<ctime>#include<cmath>#include<vector>#include<string>#include<bitset>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 1010;int n,m;ll ans,N;int gcd( int a,int b ){    return a==0?b:gcd(b%a,a);}int main(){       scanf("%d%d",&n,&m);     n++; m++; N = n*m;    ans = N*(N-1)*(N-2)/6;    ans -= N*(m-1)*(m-2)/6;    ans -= N*(n-1)*(n-2)/6;    for( int i=n;i>=2;i-- )    {        for( int j=m;j>=2;j-- )        {            ll temp = gcd( i-1,j-1 )-1;            ans -= temp*(n-i+1)*(m-j+1)*2;        }    }    printf("%lld\n",ans);    return 0;}
0 0
原创粉丝点击