标签:
自己做过的题太少了>_<
找一些tc的题来刷一刷吧 ^_^
有 y = ax+b (0 <= a < A && 0 <= b < B) 这样 A*B 条直线, 问你最终这些直线把平面分成了几部分。
考虑以a为第一关键字b为第二关键字给直线排序然后一条一条地加进去并计算贡献, 显然每一条边加进去的时候就是它和原图的交点个数+1, 因为a相同的两条直线必然没有交点, 所以可以把当前的图理解成这样 : y = cx+d(0 <= c < a && 0 <= d < B) , 他们的交点个数就是 x = (d-b)/(a-c) 有多少种取值, 即 x = (-b ~ B-b-1) / (1 ~ a) 有多少种取值, 发现分子和分母都是 < A 的且始终是自然数上的一个前缀, 于是 A^2 预处理一下就可以了。 判断 a/b 有没有在前面出现过可以直接用gcd, 不存在 c/d (0 <= c < a && 0 <= c < b) 且 c/d == a/b 当且仅当 gcd(a, b) == 1 (显然)。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define MAXN 1205 #define ll long long using namespace std; class LotsOfLines{ public: int f[MAXN][MAXN]; ll ans; int gcd(int a, int b){return b == 0 ? a : gcd(b, a%b);} ll countDivisions(int A, int B){ for(int i = 1; i < A; i ++) for(int j = 1; j < B; j ++) f[i][j] = f[i][j-1] + f[i-1][j] - f[i-1][j-1] + (gcd(i,j)==1 ? 1 : 0); for(int i = 1; i < A; i ++) for(int j = 0; j < B; j ++){ ans += (f[i][j] + f[i][B-j-1] + 1); } return ans + (ll)A*B + 1; } };
标签:
原文地址:http://www.cnblogs.com/lixintong911/p/5261535.html