https://vjudge.net/problem/UVALive-3720
题意:
有一个n行m列的点阵,问一共有多少条非水平非垂直的直线至少穿过其中的两个点。
思路:
没思路的题。
首先枚举矩形的大小,如果矩形的长宽互质,说明该斜率没出现过。
如图,1×1的矩阵的长宽互质,可以形成如图16条的直线(以1×1的矩阵为单位计算),但是如果放在整个矩阵来看,有些直线是可以合为一条直线的。
如果长宽gcd=2的话,说明该斜率的直线已经计算过了,我们要减去重复计算的。
如图,以2×2的矩阵为单位,减去1×1矩阵重复计算的直线,这样,135°斜率的直线一共有7条。
其它斜率的直线也是这样分析,详细见代码。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 using namespace std; 11 12 const int maxn=300+5; 13 14 int n,m; 15 int g[maxn][maxn]; 16 17 int gcd(int a,int b) 18 { 19 return b==0?a:gcd(b,a%b); 20 } 21 22 void init() 23 { 24 for(int i=1;i<=300;i++) 25 for(int j=i;j<=300;j++) 26 g[i][j]=g[j][i]=gcd(j,i); 27 } 28 29 int main() 30 { 31 //freopen("D:\input.txt","r",stdin); 32 init(); 33 while(~scanf("%d%d",&n,&m) && n && m) 34 { 35 n--; m--; 36 int ans=0; 37 for(int i=1;i<=n;i++) 38 { 39 for(int j=1;j<=m;j++) 40 { 41 int temp=(n-i+1)*(m-j+1); 42 if(g[i][j]==1) ans+=temp; 43 else if(g[i][j]==2) ans-=temp; 44 } 45 } 46 printf("%d ",2*ans); 47 } 48 return 0; 49 }