BZOJ 3505 浅谈组合数学在图形区域分割问题的应用
2017-07-06 09:51
381 查看
世界真的很大
在数论中,组合数和欧拉函数一样是个神奇的东西
如果说凡是看到gcd就要想到欧拉的话
那凡是看到“选几个”就应该往组合数方面想了
这种代码简单的玩意儿
难度全在于如何应用,理解的不够好,或者建模方法有问题
都是可能能卡很久的,尤其是代码量真的很短的情况下
就更悲催了
比如我就已经看了一整个晚上都没有想出来
最后还得大神指导才想到了正确的建模方法
哎。。还是不行啊。。233
还是先看题
description
给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个。下图为4x4的网格上的一个三角形。 注意三角形的三点不能共线。
input
输入一行,包含两个空格分隔的正整数m和n。
output
输出一个正整数,为所求三角形数量。
首先应该想到的是组合数
即求在m*n个点里面选3个点的组合数
但是这样是有毒的
所选的3个点有可能在一条直线上,而这种情况是不能组成三角形的
我们需要排除这样的情况
首先是三个点在同一列(行)的情况,直接算出行列,3的组合数再乘以有多少行和有多少列就好
还有就是三个点在同一斜边的情况,这个的处理就比较复杂了
考虑n^2枚举这样的斜边,再算出每条斜边3的组合数累加,整个矩阵的对角线特判一下
这样是不行的
首先会算漏。因为我们枚举的是边都在大矩形的边上的矩形的斜边,边都是整点
但有些斜边落在大矩形的边上的点并不是整点
于是考虑平移这样的斜边
这样理论上来讲是可以的,但是要考虑边长是gcd(边长)的几倍。方程化出来和下面的方法的方程是一样的
换一个角度考虑,不要枚举斜边了,直接考虑枚举在一条直线上的3个点吧,这样就不用考虑重复枚举的bug了,因为枚举的3个点肯定是不一样的。
那就考虑枚举3个点的两个端点,再用gcd算出两个端点之间有多少个整点,就有在端点确定情况下的方案数
但是呢,因为有平移的缘故,我们干脆就确定一个端点为(0,0),只枚举另一个端点的位置,整张图内能平移得到的个数就是(n-i)*(m-j)
完整代码:
#include<stdio.h> #include<algorithm> using namespace std; typedef long long dnt; dnt n,m; dnt com(dnt x) { if(x<3) return 0; return x*(x-1)*(x-2)/6; } dnt gcd(dnt a,dnt b) { return b==0 ? a : gcd(b,a%b) ; } dnt sov() { dnt rt=0; for(int i=1;i<n;i++) for(int j=1;j<m;j++) rt+=(gcd(i,j)-1)*(n-i)*(m-j); return (rt*2); } int main() { scanf("%lld%lld",&n,&m); n++,m++; printf("%lld",com(m*n)-n*com(m)-m*com(n)-sov()); return 0; }
嗯,就是这样
相关文章推荐
- BZOJ 3505: [Cqoi2014]数三角形|组合数学
- BZOJ 3207 浅谈主席树及哈希表对于区间数列存在性判断问题的应用
- bzoj 3505: [Cqoi2014]数三角形 排列组合+数学
- BZOJ 3505 [Cqoi2014]数三角形(组合数学)
- bzoj 4487: [Jsoi2015]染色问题 组合数学+容斥原理
- BZOJ 3505 CQOI2014 数三角形 组合数学
- bzoj 3505 数三角形 - 组合数学
- [bzoj3505][CQOI2014]数三角形_组合数学
- 【组合数学】BZOJ3505 [Cqoi2014]数三角形
- [BZOJ3505][Cqoi2014]数三角形(组合数学+gcd)
- bzoj 3505: [Cqoi2014]数三角形 组合数学
- 卡特兰数在多种问题下的应用 组合数学-Catalan数
- BZOJ 2982 浅谈组合数学Lucas定理
- 浅谈PHP 闭包特性在实际应用中的问题
- 母函数在排列组合问题中的应用
- poj 3270 Cow Sorting (组合数学 置换应用)
- BZOJ 2111: [ZJOI2010]Perm 排列计数(简单组合数学)
- 如何利用数学思想解1/2/5组合问题
- 数学之美——组合小事(今天看到的一个简单的组合学应用,但是觉得挺有意思的)
- 组合问题及应用