bzoj3505 [Cqoi2014]数三角形
2017-08-02 21:10
344 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=3505 [Cqoi2014]数三角形
这道题是一道计数和数论结合的题目(小学数学奥林匹克)。
先将n和m都+1,答案是n×m网格中任选三个点方案数-三点共线的情况。前者好算,
问题的关键在于斜着的情况。假设网格中有两点A(x,y),B(p,q),那么这条线段上点的个数(除去端点)就是
代码:
这道题是一道计数和数论结合的题目(小学数学奥林匹克)。
先将n和m都+1,答案是n×m网格中任选三个点方案数-三点共线的情况。前者好算,
C(n*m,3)。后者分成平行于网格线和斜着的两种情况,平行与网格线的易得
n*C(m,3)+m*C(n,3)。
问题的关键在于斜着的情况。假设网格中有两点A(x,y),B(p,q),那么这条线段上点的个数(除去端点)就是
gcd(|x-p|,|y-q|)-1个点,每个点与端点结合都能产生一组三点共线,可以直接枚举x-p,y-q,然后乘以平移出来的个数即可,具体计算方法见代码。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL c (int n, int m) { if (m > n) return 0; LL ret = 1; for (int i = 0; i < m; ++ i) ret *= n-i; for (int i = 1; i <= m; ++ i) ret /= i; return ret; } int gcd (int a, int b) {return b? gcd (b, a%b): a;} int main () { int n, m; scanf ("%d%d", &n, &m); ++n; ++ m; LL ans = c (n*m, 3); ans -= m*c (n, 3) + n*c (m, 3); for (int i = 1; i < n; ++ i) for (int j = 1; j < m; ++ j) { int x = gcd (i, j); ans -= 2*(n-i)*(m-j)*(x-1); } printf ("%lld\n", ans); return 0; }
相关文章推荐
- bzoj 3505: [Cqoi2014]数三角形
- 【BZOJ 3505】 [Cqoi2014]数三角形
- BZOJ 3505: [Cqoi2014]数三角形( 组合数 )
- bzoj 3505: [Cqoi2014]数三角形
- bzoj 3505 [Cqoi2014]数三角形 组合
- [Bzoj3505][Cqoi2014]数三角形
- BZOJ 3505: [Cqoi2014]数三角形 计数原理
- bzoj3505: [Cqoi2014]数三角形
- BZOJ 3505 CQOI2014 数三角形 组合数学
- bzoj 3505 [Cqoi2014]数三角形 组合
- 【bzoj3505】 Cqoi2014—数三角形
- BZOJ 3505 [Cqoi2014]数三角形 - gcd
- BZOJ 3505 CQOI 2014 数三角形 数学
- BZOJ 3505: [Cqoi2014]数三角形 题解
- bzoj 3505: [Cqoi2014]数三角形 数学
- bzoj 3505 [Cqoi2014]数三角形(组合计数)
- BZOJ 3505 【CQOI2014】 数三角形
- 【bzoj3505】[Cqoi2014]数三角形 容斥原理
- [组合计数] BZOJ 3505 [Cqoi2014]数三角形
- 【BZOJ 3505】[Cqoi2014]数三角形 组合数学