取三角形(排列组合 )

来源:互联网 发布:泰牛程序员 编辑:程序博客网 时间:2024/04/29 20:30

Bzoj3505 数三角形

题意:在一个n * m的方格中数出有多少以顶点组成的三角形;

思路:一共有(n + 1)* (m + 1)个点,首先有C(3,(n+ 1)*(m + 1))种组成方法,然后除去三点共线的情况就行了;

三点共线的情况如下,1,首先是在水平线上或者在垂直线上的,为(n + 1)* C(3,m+ 1) + (m + 1) * C(3,n + 1);

                                  2,接下来就是考虑斜线的情况,设i,j,代表的是两个点在一个长宽分别为i,j的矩形的两个对点,那么这两个点当成组成三角形的两个点,那么使三点共线的第三个点自然在两点之间,根据性质,中间的点的个数为gcd(i,j) - 1;然后可以正斜和负斜,*2,这个矩形可以进行上下和左右平移,所以*(m + 1 - i) *(n + 1 - j);

代码:

#include<bits/stdc++.h>using namespace std;typedef long long ll;#define MOD 2147493647const int maxn = 26;ll combine(ll y){    ll ans = y *(y - 1) * (y - 2) / 6;    return ans;}ll gcd(ll x,ll y){    if(y == 0)        return x;    return gcd(y,x % y);}int main(){    ll n,m;    while( ~ scanf("%lld%lld",&n,&m ) )    {        ll ans = combine((n + 1)*(m + 1));        ll sum = 0;        for(int i = 1; i <= n; i ++)        {            for(int j = 1; j <= m; j ++)            {                sum += (gcd(i,j) - 1)*(n + 1 - i) * (m+ 1 - j);            }        }        ans -= (combine(m+1)*(n + 1) + combine(n+ 1)*(m+ 1));        cout << ans - 2 * sum << endl;    }    return 0;}


0 0
原创粉丝点击