• Gao the Grid ZOJ 3647 数三角形


    首先从所有的点中选3个点用来画三角形,一共有ans = C((n+1)*(m+1),3)种,然后减去三点共线的情况,三点水平和垂直共线很好考虑,ans -= (n+1)*C(m+1,3)

    ans -= (m+1)*C(n+1,3).

    然后针对斜线的情况,用枚举法。

    先考虑如下的情况:

    假设有一条过原点(0,0)和点(x0,y0)的线段,其中x0,y0均为正整数,那么这条线段上有多少个整数点呢。整数点就是坐标为(x,y)的点,其中x,y均为整数 。

    答案上gcd(x0,y0)+1,下面证明:

    这条线段的方程如下:y = k * x ,其中k = y0/x0. (x>=0 && x <= x0)

    那么设y0分解为y0 = p1 * p2  ```` pk

    x0的分解为x0 = q1*q2*q3````qs其中pi,qi均为素数

    不妨设p1= q1,p2=q2,```pt =qt.剩下的pi和qj互素(i=t+1,```k,j=t+1,s),显然,p1*p1*```*pt就是gcd(x0,y0)(也就是x0 和 y0 的最大公约数)。

    那么y  = k *x,当x取值为q(t+1)*q(t+2)*```*q(s),也就是x0/gcd(x0,y0)时,y为小于y0的整数,令d = x0/gcd(x0,y0),x取值为0*d,1*d,2*d ,```` gcd(x0,y0)*d,y都会是>=0,<=y0的整数,而这样选择的x也是>=0,<=x0的整数,所有在这条线段上一共有gcd(x0,y0)个整数点。由此得证。

    这样的话,选定两个整数点(两整数点不在同一水平线或垂直线上,只考虑斜线的情况),再在这两个点组成的线段上另选一个点和这个点组成伪三角形,这样的伪三角形有多少个。

    答案是,自己好好想想,呵呵,然后先列举斜率为正的斜线,然后发现斜率为负的斜率与之对称,所以斜率为正的斜线的伪三角形的个数*2即可

    贴代码:

    View Code
     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 typedef long long LL;
     5 int gcd(int a,int b)
     6 {
     7     return b==0 ? a : gcd(b,a%b);
     8 }
     9 LL pc3(LL x)
    10 {
    11     LL y;
    12     y = x*(x-1)*(x-2)/6;
    13     return y;
    14 }
    15 int main()
    16 {
    17     int  n,m;
    18     while(~scanf("%d%d",&n,&m))
    19     {
    20         LL ans = pc3((n+1)*(m+1));
    21         ans -= (m+1)*pc3(n+1);
    22         ans -= (n+1)*pc3(m+1);
    23         for(int i=2; i<=n; ++i)
    24         {
    25             for(int j=2; j<=m; ++j)
    26             {
    27                 ans -= (long long int )(gcd(i,j)-1)*(n+1-i)*(m+1-j)*2;
    28             }
    29         }
    30         cout<<ans<<endl;
    31     }
    32     return 0;
    33 }
  • 相关阅读:
    map迭代器
    线段树——校门外的树
    并查集——C
    并查集
    数论—— LCM
    【动态规划】合唱队形
    线段树——D
    线段树——E
    逆元,exgcd,欧拉定理,费马小定理
    待学知识点
  • 原文地址:https://www.cnblogs.com/allh123/p/3022499.html
Copyright © 2020-2023  润新知