Luogu P3166 [CQOI2014]数三角形 组合数学
2024-09-08 06:32:57
好题鸭。。
不好直接求三角形个数,那就用全集-补集,转化为求三点共线的数量。
具体求法是求出水平共线数量与竖直共线数量和斜线共线数量。
用排列组合的知识可知为水平和竖直的为$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$种可能了。我们又发现,这些线段是可以平移和对称(/和\)的,于是并不需要枚举所有的两个点,只用枚举$(0,0)$和$(x,y)$,然后通过平移和对称($*2$)来计算出现的次数。
那么可以发现,这样任意一条线,向上只能平移$(n-i)$,向下$(m - j)$次,
所以出现次数就为$(n - i + 1) * (m - j + 1)$,其中$+1$是因为可以不移动
#include<iostream>
#include<cstdio>
#define ll long long
#define R register ll
using namespace std;
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m;
ll ans;
inline int gcd(int a,int b) {return b?gcd(b,a%b):a;}
signed main() {
n=g()+,m=g()+; ans=1ll*n*m;
ans=1ll*ans*(ans-)*(ans-)/-1ll*m*n*(n-)*(n-)/-1ll*n*m*(m-)*(m-)/;
for(R i=;i<n;++i) for(R j=;j<m;++j) ans-=1ll**(gcd(i,j)-)*(n-i)*(m-j);
printf("%lld\n",ans);
}
2019.06.01
最新文章
- 【探索】利用 canvas 实现数据压缩
- c# Entity DbArithmeticExpression arguments must have a numeric common type
- spring装配---处理自动装配的歧义性
- 在使用Intelligencia.UrlRewriter过程中 中文乱码问题
- NeHe OpenGL教程 第四十六课:全屏反走样
- VC++编程中常用的字符串转换函数
- angular.element方法汇总以及AngularJS 动态添加元素和删除元素
- 【Permutations】cpp
- MYSQL 排行类的相关SQL写法,仅供参考
- HEX转BIN源码分析(51系列)
- 关于DCLP实现的单例模式的一些想法
- PHP文件操作整理
- SpringMVC之HandlerMapping的使用
- 《HelloGitHub月刊》第 02 期
- 让ASP.NET Web API支持$format参数的方法
- form表单提交时action路劲问题
- 将SQL Server账户对应到Windows系统账户
- 关闭多个screen
- MyBatis框架(6)动态sql
- OpenGL入门学习(四)