2012-A3-0005
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
此题求:一个n×m的格点矩形中,三角形数量。
任意三点为一个三角形或共线,于是只要 C^3^,,(n+1)*(m+1),, - 三点共线数量即可
此题可以枚举子矩形来计算三点共共线的数量,比较好写。
我采用的是枚举斜率的方法,很容易写错
水平的垂直的计算较为简单,
然后x,y分别从1..m, 1..n,枚举只有gcd(x,y)==1才是有效斜率。
枚举完斜率再枚举斜率步长,就可以知道此斜率下线段的格点数,计算选3的组合即可。
注意:这样会使不同步长的点重复计算,可以设置一个比他小步长的矩形来规避,这样就转化为,一个矩形,中挖去一个矩形,再与两个半平面分别求交,然后求并的计算,挣扎了好久终于实现了。
这个和枚举矩形的时间复杂度是一样的,只是比较难写..
{{{
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long num;
num C3[1024];
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
for(int i=0;i<1024;++i)C3[i]=i*(i-1)*(i-2)/6;
int mx,my,mm,xx,px,py,n,m,dx,dy,pp,x,y,z;
//num tt;
for(num tot;scanf("%d%d",&n,&m)==2;printf("%llu\n",tot)){
tot =(n+1)*(m+1);
tot = tot*(tot-1)*(tot-2)/6;
tot -= C3[n+1]*(m+1);
tot -= C3[m+1]*(n+1);
for(x=1;x<=m;++x)
for(y=1;y<=n;++y)if(gcd(x,y)==1){
z = min(m/x,n/y);
if(z<2)continue;
px = m -x * z;
py = n -y * z;
tot -= (px+1)*(py+1)*2*C3[z+1];
for(--z;z>1;--z){
mx = m-x*z;
my = n-y*z;
pp = (mx+1)*(my+1)-(px+1)*(py+1);
if(mx>=x && my>=y){
pp -= (mx-x+1)*(my-y+1);
if(px>=x && py >= y){
pp+= (py-y+1)*(px-x+1);
}
}
tot -= (pp<<1)*C3[z+1];
px = mx;
py = my;
}
}
}
}
}}}
此题求:一个n×m的格点矩形中,三角形数量。
任意三点为一个三角形或共线,于是只要 C3(n+1)*(m+1) - 三点共线数量即可
此题可以枚举子矩形来计算三点共共线的数量,比较好写。
我采用的是枚举斜率的方法,很容易写错
水平的垂直的计算较为简单,
然后x,y分别从1..m, 1..n,枚举只有gcd(x,y)==1才是有效斜率。
枚举完斜率再枚举斜率步长,就可以知道此斜率下线段的格点数,计算选3的组合即可。
注意:这样会使不同步长的点重复计算,可以设置一个比他小步长的矩形来规避,这样就转化为,一个矩形,中挖去一个矩形,再与两个半平面分别求交,然后求并的计算,挣扎了好久终于实现了。
这个和枚举矩形的时间复杂度是一样的,只是比较难写..
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long num;
num C3[1024];
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
for(int i=0;i<1024;++i)C3[i]=i*(i-1)*(i-2)/6;
int mx,my,mm,xx,px,py,n,m,dx,dy,pp,x,y,z;
//num tt;
for(num tot;scanf("%d%d",&n,&m)==2;printf("%llu\n",tot)){
tot =(n+1)*(m+1);
tot = tot*(tot-1)*(tot-2)/6;
tot -= C3[n+1]*(m+1);
tot -= C3[m+1]*(n+1);
for(x=1;x<=m;++x)
for(y=1;y<=n;++y)if(gcd(x,y)==1){
z = min(m/x,n/y);
if(z<2)continue;
px = m -x * z;
py = n -y * z;
tot -= (px+1)*(py+1)*2*C3[z+1];
for(--z;z>1;--z){
mx = m-x*z;
my = n-y*z;
pp = (mx+1)*(my+1)-(px+1)*(py+1);
if(mx>=x && my>=y){
pp -= (mx-x+1)*(my-y+1);
if(px>=x && py >= y){
pp+= (py-y+1)*(px-x+1);
}
}
tot -= (pp<<1)*C3[z+1];
px = mx;
py = my;
}
}
}
}