bzoj 3505 //3505: [Cqoi2014]数三角形

bzoj 3505 //3505: [Cqoi2014]数三角形   //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=3505

更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录

//3505: [Cqoi2014]数三角形
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=3505
//刚开始读题,就发现,没图,网络中搜索了一圈,也没找到图,那就耐心读题,拿出纸笔画画
//题意在没有图的情况下弄懂了.
//数据范围1<=m,n<=1000,递归是没则了,O(n^2)的算法
//用到什么数学,2*2  76的模拟还是比较困难的.
//思路源于此文https://www.luogu.org/problemnew/solution/P3166  作者: BillYang 更新时间: 2017-07-29 21:02 代码注释
//任选3个点-共线的3个点=三角形个数
//共线3个点=水平共线+竖直共线+倾斜共线,难点在于倾斜共线的计算

(m-i)*(n-j)*(gcd(i,j)+1-2)*2;//倾斜共线   理解如下,以2*2为例,自加1,m=3,n=3

i=1,j=1

(m-i)*(n-j)=(3-1)*(3-1)=4  4指边长为1*1的矩形有4个;

gcd(i,j)+1-2=gcd(1,1)+1-2=0,是指(0,0)-(1,1)这个线段中间有几个点(首尾两个点不算)

*2原因是下图中,1*1的对角线有2个,实线,虚线各1个。

bzoj 3505 //3505: [Cqoi2014]数三角形_第1张图片

i=1,j=2

(m-i)*(n-j)=(3-1)*(3-2)=2  2指边长为1*2的矩形有2个;

gcd(i,j)+1-2=gcd(1,2)+1-2=0,是指(0,0)-(1,2)这个线段中间有几个点(首尾两个点不算)

*2原因是下图中,1*2的对角线有2个,实线,虚线各1个。

bzoj 3505 //3505: [Cqoi2014]数三角形_第2张图片

i=2,j=1

(m-i)*(n-j)=(3-2)*(3-1)=2  2指边长为2*1的矩形有2个;

gcd(i,j)+1-2=gcd(2,1)+1-2=0,是指(0,0)-(2,1)这个线段中间有几个点(首尾两个点不算)

*2原因是下图中,2*1的对角线有2个,实线,虚线各1个。

bzoj 3505 //3505: [Cqoi2014]数三角形_第3张图片

i=2,j=2

(m-i)*(n-j)=(3-2)*(3-2)=1  1指边长为2*2的矩形有1个;

gcd(i,j)+1-2=gcd(2,2)+1-2=1,是指(0,0)-(2,2)这个线段中间有几个点(首尾两个点不算)

*2原因是下图中,2*2的对角线有2个,实线,虚线各1个。

bzoj 3505 //3505: [Cqoi2014]数三角形_第4张图片

至于倾斜直线算法,为什么不会有遗漏,为什么不会有重复,请读者自行画图,多画画,应该能理解。2019-8-30 16:04
//该题数量庞大,采用long long
//样例通过,提交AC.2019-8-30 14:49
#include
#define LL long long
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int main(){
    int i,j;
    LL ans,m,n;
    scanf("%lld%lld",&m,&n),m++,n++;
    ans=m*n*(m*n-1)*(m*n-2)/(3*2*1);//任选3个点数 C(n,3) 全集
    if(n>=3)ans-=n*(n-1)*(n-2)/(3*2*1)*m;//水平共线
    if(m>=3)ans-=m*(m-1)*(m-2)/(3*2*1)*n;//竖直共线
    for(i=1;i         for(j=1;j             if(gcd(i,j)+1-2>0)ans-=(m-i)*(n-j)*(gcd(i,j)+1-2)*2;//倾斜共线
    printf("%lld\n",ans);
}

你可能感兴趣的:(跟着大佬学算法)