ans=C((n+1)*(m+1),3)-三点一线的情况
横线竖线我们可以先去掉
然后考虑斜线,由于对称性我们只要考虑斜率大于0的即可
有一个很显然的结论,但两点坐标差为x,y时,这条线段上的点数为gcd(x,y)
我们设左下角点为(0,0),则两端点坐标差为x,y的线段有(n-x+1)*(m-y+1)
要注意同在一条直线上不能重复计算,我们考虑线段更容易一点
所以,对于每条线段,三点一线的情况为除去两端点的线段上点数

 1 var i,j,n,m:longint;
 2     ans,tmp:int64;
 3 function calc(x:int64):int64;
 4   begin
 5     exit(x*(x-1)*(x-2) div 6);
 6   end;
 7 
 8 function gcd(a,b:longint):longint;
 9   begin
10     if b=0 then exit(a)
11     else exit(gcd(b,a mod b));
12   end;
13 
14 begin
15   readln(n,m);
16   ans:=calc((n+1)*(m+1))-(n+1)*calc(m+1)-(m+1)*calc(n+1);
17   for i:=1 to n do
18     for j:=1 to m do
19     begin
20       tmp:=gcd(i,j)+1;
21       if tmp>2 then
22         ans:=ans-2*(n-i+1)*(m-j+1)*(tmp-2);
23     end;
24   writeln(ans);
25 end.
26 
27  
View Code

 

posted on 2014-10-26 17:16  acphile  阅读(108)  评论(0编辑  收藏  举报