码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-06-01 15:13:30      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:sign   getch   long   register   nbsp   mes   str   inline   etc   

好题鸭。。

不好直接求三角形个数,那就用全集-补集,转化为求三点共线的数量。

具体求法是求出水平共线数量与竖直共线数量和斜线共线数量。

用排列组合的知识可知为水平和竖直的为$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=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==-?-1:fix;
    do ret=ret*10+(ch^48); 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()+1,m=g()+1; ans=1ll*n*m;
    ans=1ll*ans*(ans-1)*(ans-2)/6-1ll*m*n*(n-1)*(n-2)/6-1ll*n*m*(m-1)*(m-2)/6;
    for(R i=1;i<n;++i) for(R j=1;j<m;++j) ans-=1ll*2*(gcd(i,j)-1)*(n-i)*(m-j);
    printf("%lld\n",ans);
}

2019.06.01

 

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

标签:sign   getch   long   register   nbsp   mes   str   inline   etc   

原文地址:https://www.cnblogs.com/Jackpei/p/10958377.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!