【bzoj3505】【CQOI2014】【数三角形】【组合数学】

Description

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

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

Input

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

Output

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

Sample Input

2 2

Sample Output

76

数据范围

1<=m,n<=1000

题解:考虑补集,先把答案赋为c(n*m)(3),然后减去三点共线的情况。

首先三点在一条水平或竖直的直线上非常好处理。直接减去c(n)(3)*m+c(m)(3)*n即可。

然后考虑不水平竖直的情况。

我们枚举一下边上两个点的横纵坐标之差(i,j)。那么中间的点可选的位置就是gcd(i,j)-1;然后再乘上这种直线的条数即可。注意要先处理组合数,要不然会爆的很惨。

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,temp;
long long ans,c[1000001][5];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main()
{
   	scanf("%d%d",&n,&m);n++;m++;
   	c[0][0]=1;
    for(int i=1;i<=n*m;i++)
     {
       c[i][0]=1;
       for(int j=1;j<=3;j++) c[i][j]=c[i-1][j-1]+c[i-1][j];
     }
    ans=c[n*m][3];
   	ans-=n*c[m][3];
   	ans-=m*c[n][3];
   	for (int i=1;i<n;i++)
   	  for (int j=1;j<m;j++)
   	    {
   	      temp=gcd(i,j);
   	      if (temp>1) ans-=(temp-1)*2*(n-i)*(m-j);
   	    }
   	cout<<ans<<endl;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-26 04:53:50

【bzoj3505】【CQOI2014】【数三角形】【组合数学】的相关文章

BZOJ 3505 CQOI2014 数三角形 组合数学

题目大意: 给定一个m*n的方格.求上面有多少个格点三角形 m,n<=1000 枚举O(m^3*n^3).铁定超时 我们选择补集法 首先我们随意选择三个不反复的点构成三角形 用组合数算出这一值 然后刨除三点一线的点就可以 枚举三点之中在两边的点的横纵坐标之差,中间点的位置数为GCD(x,y)-1,统计答案就可以 注意初始计算组合数时可能会爆int #include<cstdio> #include<cstring> #include<iostream> #incl

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(

[bzoj3505 Cqoi2014] 数三角形 (容斥+数学)

传送门 Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和n. Output 输出一个正整数,为所求三角形数量. Sample Input 2 2 Sample Output 76 HINT 1<=m,n<=1000 Solution 首先思路肯定是随意三个点方案-三点共线方案 随意三个点方案随意求 主要求三点共线: 有个神奇的结论:节点坐标gc

【排列组合】bzoj3505 [Cqoi2014]数三角形

http://blog.csdn.net/zhb1997/article/details/38474795 #include<cstdio> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; int n,m; ll ans; int main() { // freopen("bzoj3505.in","r",stdin

bzoj3505 [Cqoi2014]数三角形

题目链接 先算在n*m个点中任选3个的方案数,再减去三点共线的方案数 我为什么要做这种水题?因为我很弱 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include<cmath> 8 #include<ctime>

Luogu P3166 [CQOI2014]数三角形 组合数学

好题鸭.. 不好直接求三角形个数,那就用全集-补集,转化为求三点共线的数量. 具体求法是求出水平共线数量与竖直共线数量和斜线共线数量. 用排列组合的知识可知为水平和竖直的为$C_n^3$?与$C_m^3?$. 求斜线三点共线:显然,对于点$(a,b) (x,y)$连成的线段$(其中a>x,b>y)$,在它们中间有$gcd(a-x,b-y)-1$个整点,因此基本的思路就是枚举两个点,然后第3个点就是$gcd(a-x,b-y)-1$种可能了.我们又发现,这些线段是可以平移和对称(/和\)的,于是并

【BZOJ3505】[Cqoi2014]数三角形 组合数

[BZOJ3505][Cqoi2014]数三角形 Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和n. Output 输出一个正整数,为所求三角形数量. Sample Input 2 2 Sample Output 76 数据范围 1<=m,n<=1000 题解:显然要用补集法,我们只需要求出三点共线的方案数即可.方法是先枚举两端的点所形成的向

bzoj3505 / P3166 [CQOI2014]数三角形

P3166 [CQOI2014]数三角形 前置知识:某两个点$(x_{1},,y_{1}),(x_{2},y_{2})\quad (x_{1}<x_{2},y_{1}<y_{2})$所连成的线段穿过整点的个数为$gcd(x_{2}-x_{1},y_{2}-y_{1})-1$ “注意三角形的三点不能共线.” 暗示你可以处理出总方案再减去三点共线的方案. 显然,总方案就是在$(n+1)*(m+1)$个点中任选$3$个.于是$tot=C((n+1)*(m+1),3)$ 现在我们要算出三点共线的方案

BZOJ 3505: [Cqoi2014]数三角形( 组合数 )

先n++, m++ 显然答案就是C(3, n*m) - m*C(3, n) - n*C(3, m) - cnt. 表示在全部点中选出3个的方案减去不合法的, 同一行/列的不合法方案很好求, 对角线的不合法方案cnt比较麻烦. 枚举对角线(左下-右上), 即(0, 0)-(x, y), 我们发现这种情况有(n-y)*(m-x)*2(算上左上-右下的)种, 然后中间有gcd(x, y)-1个点(不合法), 乘起来就好了. ---------------------------------------

3505: [Cqoi2014]数三角形

3505: [Cqoi2014]数三角形 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1324  Solved: 807[Submit][Status][Discuss] Description 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Input 输入一行,包含两个空格分隔的正整数m和n. Output 输出一个正整数,为所求三角形数量. Sample Inp