The topic of the topic
There is a \ (n\) row \ (m\) column (\ (1≤n, m≤300\)) of the lattice, Q: How many non-horizontal non-vertical straight line at least through the two points? For example, \ (n = 2\), \ (M = 4\) When the answer is \ (12\), \ (n = m = 3\) The answer is \ (14\).
Exercises
When I first saw the topic I immediately thought of \ (SPOJ 104 highways\)(Kirchhoff Matrix-tree theorem), but the subject has nothing to do with this theorem.
The first consideration is how to determine whether a straight line has not appeared before, and if it greatest common divisor the vector two coordinate is \ (1\) . We consider using \ (dp_{i\ j}\) to indicate how many \ ((x, y) ( y≤j\)) of the Vector \ (( x, y) \)((x≤i\) = 1\) , the recursive type is:
\[dp_{i\ J} = dp_{i-1\ J} + dp_{i\ J-1}-dp_{i-1\ J-1} ((i, j) ≠1) \]
\[dp_{i\ J} = dp_{i-1\ J} + dp_{i\ J-1}-dp_{i-1\ J-1} + 1 ((i, j) = 1) \]
Next processing all points, to \ ((i, j) \) , the internal points and his vector range are in \ (\{(x, y) |x∈[1, i), Y∈[1, J), X, y∈n^*\}\) , then you can use \ (Dp_{i- 1\ j-1}\) indicates how many of them are coprime, minus the repeated calculations (\ (dp_{\frac{i-1}{2}\ \frac{j-1}{2}}\)). For convenience we will all \ (i\), \ (j\) increase \ (1\), last minus \ (1\) can.
Code
#include <cstdio>long long ans[310][310], dp[310][310];int n, m;inline long long GreatestCommonDivisor(const long long&, const long long&);int main(int argc, char const *argv[]) { for (register long long i(1); i <= 300ll; ++i) { for (register long long j(1); j <= 300ll; ++j) { dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + (GreatestCommonDivisor(i, j) == 1); ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1] + dp[i][j] - dp[i >> 1][j >> 1]; } } while (~scanf("%d %d", &n, &m) && (n || m)) { printf("%lld\n", ans[n - 1][m - 1] << 1); } return 0;}inline long long GreatestCommonDivisor(const long long &a, const long long &b) { return b ? GreatestCommonDivisor(b, a % b) : a;}
UVa 1393 Highways (Dynamic planning)