uva 12075 - Counting Triangles(容斥原理)

来源:互联网 发布:sql中with as的用法 编辑:程序博客网 时间:2024/05/02 02:56

题目链接:uva 12075 - Counting Triangles

题目大意:一个nm的矩阵,求说有选任意三点,可以组成多少个三角形。

解题思路:任意选三点C(3(n+1)(m+1))但是有些组合是不可行得,即为三点共线,除了水平和竖直上的组合,就是斜线上的了,dp[i][j]即为ij情况下的斜线三点共线。

#include <cstdio>#include <cstring>typedef long long ll;const int N = 1005;ll dp[N][N];ll gcd (ll a, ll b) {    return b == 0 ? a : gcd(b, a%b);}void init () {    for (int i = 2; i < N; i++)        for (int j = 2; j < N; j++)            dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + gcd(i, j) - 1;    for (int i = 2; i < N; i++)        for (int j = 2; j < N; j++)            dp[i][j] += dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1];}ll C(ll n, ll m) {    if (n < m)        return 0;    ll ans = 1;    for (ll i = 0; i < m; i++)        ans = ans * (n-i) / (i+1);    return ans;}ll solve (ll n, ll m) {    return C((n)*(m), 3) - C(n, 3) * m - C(m, 3) * n;}int main () {    int cas = 1;    ll n, m;    init();    while (scanf("%lld%lld", &n, &m) == 2 && n && m) {        printf("Case %d: %lld\n", cas++, solve(n+1, m+1)-dp[n][m]*2);    }    return 0;}
1 0
原创粉丝点击