zoukankan      html  css  js  c++  java
  • bzoj3505: [Cqoi2014]数三角形 [数论][gcd]

    Description

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

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

    Input

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

    Output

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

    Sample Input

    2 2

    Sample Output

    76

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

    太伤心了。。不能abs(int)???

    首先格点个数是(n+1)*(m+1)的,所以我们先把n和m都+1。 先选出三个不同点,方案数是C(n*m,3)。 接下来扣掉三点共线的情况。 枚举两个点,计算以它们为端点的线段上的整点个数。 不难发现是gcd(x1-x2,y1-y2)-1。 线段是可以平移的,那么我们把其中一个点固定在(0,0),只枚举另一个点的坐标,然后乘上方案数就行了。 时间复杂度O(nm)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 #define dbg(x) cout<<#x<<" = "<<x<<endl
     6 
     7 typedef long long ll;
     8 
     9 const int maxn=1005;
    10 
    11 int n,m,f[maxn][maxn],ens;
    12 ll ans;
    13 
    14 ll C(int a,int b){
    15     ll res=1;
    16     for(int i=a;i>a-b;i--)  res*=i;
    17     for(int i=b;i>1;i--)  res/=i;
    18     return res;
    19 }
    20 
    21 int gcd(int a,int b){
    22     if(f[a][b])  return f[a][b];
    23     return b?(f[a][b]=gcd(b,a%b)):a;
    24 }
    25 
    26 int main(){
    27     scanf("%d%d",&n,&m);
    28     n++;  m++;
    29     ans=C(n*m,3);
    30     for(int i=-n+1;i<=n-1;i++)
    31         for(int j=0;j<=m-1;j++){
    32             //避免重复计算 
    33             if(!j&&i<=0)  continue;
    34             ens=gcd(i<0?-i:i,j)-1;
    35 //            dbg(abs(i));  dbg(j);  dbg(ens);
    36             ans-=1ll*ens*(n-(i<0?-i:i))*(m-j);
    37         }
    38     printf("%lld
    ",ans);
    39     return 0;
    40 }
  • 相关阅读:
    Swift
    iOS 拨打电话
    UI控件问题和XCode编译警告和错误解决方法集锦 (持续更新ing)
    让UIWebView弹出键盘上的按钮显示中文 (附效果图)
    启动app时全屏显示Default.png (附效果图)
    三种数据存储 (plist,NSUserDefaults存储,NSKeyedArchiver存模型方法)
    生成圆形头像 (附效果图)
    循环按钮,并且选中 (附效果图)
    leetcode 字符串分割对称
    leetcode merge-sorted-array/
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/7284430.html
Copyright © 2011-2022 走看看