Bzoj 3505: [Cqoi2014]数三角形 数论

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
 
题解:
数论
首先,我们可以将问题转化一下, 可以形成的三角形的个数=任选三个点的个数-三点共线个数
设总点数为k,则k=(n+1)*(m+1)
任选三个点的个数很简单:(k*(k-1)*(k-2))/6
至于三点共线个数,我们可以发现枚举每个点(i,j),则 (i,j) 和 (1,1) 再和 其他的一个点 能共线的个数为Gcd(i,j)-1,还有,因为我们枚举的点为(i,j),我们可以把(1,1)和(i,j)看为一个矩形,那么明显是可以在大的矩形中移动的。也就是我们算的线为(1,1)到(i,j)的线,但是其平行的线我们还要再算的,所以用 每个点的个数乘上(n-i+1)*(m-j+1)。然后我们把所有的点都计算一遍,然后把 和 乘2(因为我们刚才考虑的为从左下角往右上角偏的,不一定是平行,也就是和这个箭头差不多的方向↗️。我们还要考虑这种样子的↖️,显然两种的个数相等,所以要乘2。)最后,我们发现左右的线↔️和上下的线↕️没有减去,所以要单独减。
 
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long 
 4 LL Gcd(int aa,int bb){if(bb==0)return aa;else return Gcd(bb,aa%bb);}
 5 int main()
 6 {
 7     LL n,m,k,k1,ans,i,j,tot=0;
 8     scanf("%lld %lld",&n,&m);
 9     k=(n+1)*(m+1);
10     ans=k*(k-1)*(k-2)/6;
11     for(i=1;i<=n;i++)
12     {
13         for(j=1;j<=m;j++)
14         {
15             k=Gcd(i,j);
16             if(k>=2)tot+=(k-1)*(n-i+1)*(m-j+1);
17         }
18     }
19     n++;m++;
20     k=m*(m-1)*(m-2)/6;
21     k1=n*(n-1)*(n-2)/6;
22     ans-=(n*k+m*k1);
23     printf("%lld",ans-tot*2);
24     fclose(stdin);
25     fclose(stdout);
26     return 0;
27 }

 

转载于:https://www.cnblogs.com/Var123/p/5377616.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值