至于三点共线个数,我们可以发现枚举每个点(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 }