UVA - 1393 Highways

Description

Hackerland is a happy democratic country with m×n cities, arranged in a rectangular
m by n grid and connected by
m roads in the east-west direction and
n roads in the north-south direction. By public demand, this orthogonal road system is to be supplemented by a system of highways in sucha way that there will be a direct connection between any pair of cities. Each highway is a straight line
going through two or more cities. If two cities lie on the same highway, then they are directly connected.If two cities are in the same row or column, then they are already connected by the existing orthogonal road system (each east-west road connects all
the m cities in that row and each north-south road connects all the
n cities in that column), thus no new highway is needed to connect them. Your task is to count the number of highway that has to be built (a highway that goes through several cities on a straight line is counted as a single
highway).

Input

The input contains several blocks of test cases. Each test case consists of a single line containing two integers
1n ,
m300 , specifying the number of cities. The input is terminated by a test case with
n = m = 0 .

Output

For each test case, output one line containing a single integer, the number of highways that must be built.

Sample Input

2 4
3 3
0 0

Sample Output

12
14
题意:有一个n行m列的点阵,问一共有多少条非水平非竖直的直线至少穿过其中的两个点。
思路:这题分两步,首先计算出从点[1, 1]到[n, m]格子组成的边界的连线,然后这是需要容斥去重的,这个有新的数能加的可能是当维度i和j是互质的时候就会多一个,
然后就是递推n*m的格子的总个数,也要容斥去重,这个就是减去减半的数,这个是因为会重线,最后是对称,从左上到右下,和从坐下到右上
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn = 310;

int n, m;
ll dp[maxn][maxn], ans[maxn][maxn];

int gcd(int a, int b) {
	return b==0?a:gcd(b, a%b);
}

void init() {
	memset(dp, 0, sizeof(dp));
	memset(ans, 0, sizeof(ans));

	for (int i = 1; i <= 300; i++)
		for (int j = 1; j <= 300; j++)
			dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + (gcd(i, j) == 1);

	for (int i = 1; i <= 300; i++)
		for (int j = 1; j <= 300; j++)
			ans[i][j] = ans[i-1][j] + ans[i][j-1] - ans[i-1][j-1] + dp[i][j] - dp[i>>1][j>>1];
}

int main() {
	init();
	while (scanf("%d%d", &n, &m) != EOF && n+m) {
		printf("%lld\n", ans[n-1][m-1] * 2);
	}
	return 0;
}

UVA - 1393 Highways,布布扣,bubuko.com

时间: 2024-10-01 00:39:04

UVA - 1393 Highways的相关文章

uva 1393 - Highways(容斥原理)

题目连接:uva 1393 - Highways 题目大意:给定一个m?n的矩阵,将矩阵上的点两两相连,问有多少条直线至少经过两点. 解题思路:头一次做这样的题目,卡了一晚上. dp[i][j]即为i?j的矩阵中有多少条红色的线,然后最后答案*2,即水平翻转下蓝色的线.非常easy发现,全部的线都过ij互质的点(即最大公约数为1).然后用容斥原理求出ans. #include <cstdio> #include <cstring> const int N = 305; int n,

UVA 1393 - Highways (容斥原理计数)

题目链接:1393 - Highways 题意:给定一个n * m的点阵,问两两相连后,能组成多少条至少穿过两个点的直线,并且不是水平或垂直的 思路:找过两点的线段,由于是整数坐标,只要他的斜率不是整数,即x / y不是整数就能满足答案,然后先记录下这所有的位置,然后利用容斥原理求出对应每个点可以连出多少条这样的线段,最后去求和,求和的时候要注意,由于有一些是重复计算了,比如1 1 和 2 2 连,2 2 和 3 3 连,这样其实是算一条的,所以最后在求和的时候要扣掉重复的部分,直接减去sum[

UVa 1393 Highways (动态规划)

题目 题目大意 有一个\(n\)行\(m\)列(\(1 ≤ n, m ≤ 300\))的点阵, 问: 一共有多少条非水平非竖直的直线至少穿过其中两个点? 例如, \(n = 2\), \(m = 4\)时答案为\(12\), \(n = m = 3\)时答案为\(14\). 题解 一开始看到题目我立马想到了\(SPOJ 104 Highways\)(基尔霍夫矩阵-树定理), 然而本题跟这个定理完全没有关系. 首先考虑如何判断是否形成一条之前没有出现过的直线, 如果它向量两坐标的最大公约数为\(1

UVA 1393 Highways(数学思想)

题意:给你n.m(n,m<=200),问你有多少条非水平.非垂直的直线有多少条经过至少两个点 题解:我们需要枚举的是只画一条线的矩形,对于大小a*b的矩形必须保证gcd(a,b)=1才能不重复 接着对于每个矩形可以放的位置有(n-a)(m-b)个,但是如果有矩形在某个矩形的左上方就会再次重复 因此只需要再减去max(0,n-2*a)*max(0,m-2*b)就好 import java.util.Scanner; public class Main{ static int Max=305; st

UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)

先看第一题,有n*m个点,求在这些点中,有多少条直线,经过了至少两点,且不是水平的也不是竖直的. 分析:由于对称性,我们只要求一个方向的线即可.该题分成两个过程,第一个过程是求出n*m的矩形中,dp[i][j]代表在这个矩形中终点是到(i,j)这个点的满足题意的直线条数,那么,用dp的话就可以得出递推关系:由长和宽分别小1的左右两个矩形中满足题意的线的条数减去他们共有的矩形中满足的线的条数(容斥减去重复部分),之后还要判断从最左上角的点(1,1)到(i,j)是否可以组成一条线,这个条件是gcd(

UVa 1393 (容斥原理、GCD) Highways

题意: 给出一个n行m列的点阵,求共有多少条非水平非竖直线至少经过其中两点. 分析: 首先说紫书上的思路,编程较简单且容易理解.由于对称性,所以只统计“\”这种线型的,最后乘2即是答案. 枚举斜线包围盒的大小,如果盒子的长宽ab互质,则是可以的.这种盒子共有(m-a)(n-b)个,但要减去其中重复的.如果有一个长宽为2a和2b的大盒子,则计数右下角的小盒子的同时,左上角的小盒子会重复,所以要减去重复的盒子的个数c = max(0, m-2a) * max(0, n-2b) 最后gcd(a, b)

1393 - Highways 计数问题

Hackerland is a happy democratic country with m×n cities, arranged in a rectangular m by ngrid and connected by m roads in the east-west direction and n roads in the north-south direction. By public demand, this orthogonal road system is to be supple

UVa 10147 - Highways

题目:在一个平面上有很多点,其中一些点已经被直线段连接,现在要把所有点连成一个整体, 要求新加入的直线段长度和最小. 分析:最小生成树.这里使用kruskal算法,先把一直线段的集合合并(并查集),然后在计算即可. 说明:╮(╯▽╰)╭. #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include

1393 - Highways(问题抽象)(容斥原理计数)

问题的方向是对称的,统计\*2即可,当gcd(a,b)>1及重复, 证:a*b满足gcd(a,b)>1,在他对角线和a'和b'对角线是同一条直线(a'=a/gcd(a,b)b'=b/gcd(a,b)) 其次,如果放置位置不够靠左,也不够靠上,则它和它"左上方"的包围盒也重复了 假定左上角坐标(0,0)则对于左上角在(x,y)的包围盒,其左上方的包围盒的左上角为(x-a,y-b),这个左上角合法条件是x-a>=0,y-b>=0 包围盒本身不出界的条件是x+a<