zoukankan      html  css  js  c++  java
  • BSOJ 3899 -- 【CQOI2014】 数三角形

    Description

      给定一个n*m的网格,请计算三个点都在格点上的三角形共有多少个。下图为4*4的网格上的一个三角形。 
              
      注意三角形的三点不能共线。

    Input

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

    Output

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

    Sample Input

    样例输入1:1 1

    样例输入2:2 2

    Sample Output

    样例输出1:4

    样例输出2:76

    先求出全集,再去掉三点共线的情况。

    那如何枚举三点共线的情况呢?先将横竖两种情况算了,再考虑斜着的。枚举斜着的方法有很多,但比较可行的是先固定两个点,再计算两个点之间的点数。具体实现就是枚举两点的相对位置,也可以理解为向量(a,b),然后就有(n+1-a)*(m+1-b)个位置可以当左上角的点。这两点之间的点数就是gcd(a,b)-1。最后还要*2,对称性嘛。

    这么枚举的好处是,两点之间的相对位置去确定了之后,中间点的数量就确定了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #include<ctime>
    #define ll long long
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    ll n,m;
    ll ans,tot;
    ll gcd(ll a,ll b) {return !b?a:gcd(b,a%b);}
    int main() {
    	n=Get(),m=Get();
    	n++,m++;
    	tot=n*m;
    	ans=tot*(tot-1)/2*(tot-2)/3;
    	if(n>=3) ans-=n*(n-1)/2*(n-2)/3*m;
    	if(m>=3) ans-=m*(m-1)/2*(m-2)/3*n;
    	for(int i=1;i<n;i++) {
    		for(int j=1;j<m;j++) {
    			ans-=(n-i)*(m-j)*(gcd(i,j)-1)*2;
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    Docker_使用Rancher管理docker(7)
    Docker_部署本地镜像仓库(6)
    Python_多任务:进程、线程、协程
    JMeter_实现算法加密
    Docker_创建自定义镜像(5)
    Fiddler Everywhere简单使用
    Docker_容器(container)使用(4)
    Docker_镜像(image)使用(3)
    C#读写锁ReaderWriterLockSlim的使用
    C++二级指针第三种内存模型
  • 原文地址:https://www.cnblogs.com/hchhch233/p/9735818.html
Copyright © 2011-2022 走看看