• 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;
    }
    
  • 相关阅读:
    Linux基础(Ubuntu16.04):安装vim及配置
    Ubuntu16.04 安装ROS及其IDE
    python格式转换的记录
    python爬虫selenium相关
    【LAMP】搭建Web网站过程中的记录【Ubuntu18.04+Apache2.4+PHP7.2+MySQL5.7】
    【疯狂挖坑】linux服务器尝试中的问题(nohup等)
    逻辑回归与全连接神经网络联系的简单理解记录
    Unity3d开发中遇到的问题记录
    python中numpy库的一些使用
    Deep Learning论文翻译(Nature Deep Review)
  • 原文地址:https://www.cnblogs.com/hchhch233/p/9735818.html
Copyright © 2020-2023  润新知