• P3166 [CQOI2014]数三角形(组合数+数论+思维)


    题目描述

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

    输入输出格式

    输入格式:

     

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

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 复制
    2 2
    输出样例#1: 复制
    76

    说明

    数据范围

    bzoj上是1<=m,n<=1000




    以为有啥推的关系,后来发现不好推,就开始想怎么算。

    总方案数 C ( (n+1)*(m+1) ,3 );

    在减去三点一线的  水平,竖直的,斜着的

    前两个好算

    对于斜着的

    枚举对角线(左下-右上), 即(0, 0)-(x, y), 我们发现这种情况有(n-y)*(m-x)*2(算上左上-右下的)种, 然后中间有gcd(x, y)-1个点(不合法), 乘起来就好了 我们枚举一下边上两个点的横纵坐标之差(i,j)。 那么中间的点可选的位置就是gcd(i,j)-1;然后再乘上这种直线的条数即可






     1 #include "bits/stdc++.h"
     2 #define inf 1000000000;
     3 using namespace std;
     4 typedef long long ll;
     5 
     6 int n,m;
     7 
     8 ll C(ll a, ll b)
     9 {
    10     if(b>a) return 0;
    11     else if(b==a)return 1;
    12     else return a*(a-1)*(a-2)/6; 
    13 }
    14 
    15 int main()
    16 {
    17    cin>>n>>m; ll tot=(n+1)*(m+1);
    18    ll ans=tot*(tot-1)*(tot-2);
    19    ans/=6;
    20    ll t1=n/2,t2=m/2;
    21    //cout<<ans<<endl;
    22    ans-=C(n+1,3)*(m+1);
    23    ans-=C(m+1,3)*(n+1);
    24   // if(n+1>=3)ans-=(n+1-3+1)*(m+1);
    25   // if(m+1>=3) ans-=(m+1-3+1)*(n+1);
    26    for (int i=1;i<=n;i++)
    27     for (int j=1;j<=m;j++)
    28     {
    29         ans-=(n-i+1)*(m-j+1)*(__gcd(i,j)-1)*2;
    30     }
    31    
    32    cout<<ans;
    33    
    34    
    35 
    36 }
  • 相关阅读:
    DS博客作业05--查找
    DS博客作业04--图
    DS博客作业03--树
    DS博客作业02--栈和队列
    DS01-线性表
    C博客作业06-结构体&文件
    C博客作业05--指针
    C博客作业04--数组
    C博客作业03--函数
    C博客作业02--循环结构
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10657714.html
Copyright © 2020-2023  润新知