zoukankan      html  css  js  c++  java
  • BZOJ3505 [Cqoi2014]数三角形

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

    Description

    给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个。下图为4x4的网格上的一个三角形。

    注意三角形的三点不能共线。

    Input

    输入一行,包含两个空格分隔的正整数m和n。

    Output


    输出一个正整数,为所求三角形数量。

    Sample Input


    2 2

    Sample Output

    76


    数据范围
    1<=m,n<=1000

    正解:组合数学

    解题报告:

      这道题高一NOIP停课的时候考过原题...

      正难则反,无法直接求三角形的数量就可以考虑所有的方案减去不构成三角形的情况。

      显然只选出三个点的方案数为C((n+1)*(m+1),3),减去横着的:(m+1)*C(n+1,3),和竖着的:(n+1)*C(m+1,3)再减掉斜着的。斜着的计算起来比较复杂,考虑如果我只讨论经过左下角那个点(不妨设为原点)的情况,那么在我枚举了另一个端点(i,j)之后就可以唯一的确定一条直线,而这条直线上的点数可以用gcd(i,j)+1来表示,这个应该还比较好理解,就是得到一个直线解析式或者用相似来理解也行。只有在点数大于2的时候才会有贡献,且我们考虑这条直线可以平移,并且可以关于y轴对称后再平移,所以贡献就很明了了。

      即ans=$C ^ {3}_{(n+1)*(m+1)}$ $ -  (m+1)* C ^ {3}_{n+1}  -$ $(n+1)* C ^ {3}_{m+1}-$斜着的方案数

      斜着的方案数求法看代码吧......

        ps:我为了追求速度,预处理了两两的gcd,并且把组合数递推换成了直接暴力算。 

     1 //It is made by ljh2000
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #include <string>
    14 using namespace std;
    15 typedef long long LL;
    16 const int MAXN = 1011; 
    17 int n,m,G[MAXN][MAXN];
    18 LL ans;
    19 inline int gcd(int x,int y){ if(y==0) return x; return gcd(y,x%y); }
    20 inline int getint(){
    21     int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
    22     if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    23 }
    24 
    25 inline void work(){
    26     n=getint(); m=getint(); n++; m++; if(n<m) swap(n,m); LL lim=n*m; int now;
    27     ans=lim*(lim-1)*(lim-2)/6; ans-=(LL)m*n*(n-1)*(n-2)/6; ans-=(LL)n*m*(m-1)*(m-2)/6; 
    28     for(int i=1;i<n;i++) for(int j=i;j<n;j++) G[i][j]=gcd(i,j),G[j][i]=G[i][j];
    29     for(int i=1;i<n;i++) 
    30         for(int j=1;j<m;j++) {
    31             now=G[i][j]; now++;
    32             if(now>2) ans-=2*(now-2)*(n-i)*(m-j);
    33         }
    34     printf("%lld",ans);
    35 }
    36 
    37 int main()
    38 {
    39     work();
    40     return 0;
    41 }
  • 相关阅读:
    CSS 实现隐藏滚动条同时又可以滚动
    手机端自适应布局demo
    手机端自适应布局demo
    手机端自适应布局demo
    七个帮助你处理Web页面层布局的jQuery插件
    一笔画问题
    数组模拟邻接表
    邻接矩阵存图
    BFS 遍历图
    DFS 遍历图
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6219637.html
Copyright © 2011-2022 走看看