BZOJ 3505 【CQOI2014】 数三角形
Description
給定一個nxm的網格,請計算三點都在格點上的三角形共有多少個。
下圖為4x4的網格上的一個三角形。
注意三角形的三點不能共線。
Input
輸入一行,包含兩個空格分隔的正整數m和n。
Output
輸出一個正整數,為所求三角形數量。
HINT
數據范圍
$1\leqslant m,n \leqslant 1000$
?
這道題一眼看去有一個非常顯然的想法,那就是先用組合數算出任選三點出來的方案數,最后再減去三點共線的情況即可。那么關鍵就在于如何求三點共線的數目。
首先,我們要用到一個公式:設兩個整點分別為$(x_1,y_1)$,$(x_2,y_2)$,那么兩點之間連線上的整點數目為$gcd(|x_2-x_1|,|y_2-y_1|)$。
我覺得這個公式需要證明一下(其實很簡單)。
首先,這條直線可以平移一下,使得$x_1=y_1=0$。為了考慮方便,我們這里還設$x_2 \geqslant 0,y_2 \geqslant 0$
設$\Delta x=x_2,\Delta y =y_2$(只是為了好看一點),連線上整點的坐標為$(x,y)$,那么顯然有:$$\frac{x}{\Delta x}=\frac{y}{\Delta y}$$
設$r=gcd(\Delta x,\Delta y)$,$\Delta x=ar$,$\Delta y=br$,那么有:$$xb=ya$$
由于$a,b$互質,$x,y$為整數,于是我們就得到了$$x=ka,y=kb(k \in Z)$$;
由于$0 \leqslant x \leqslant \Delta x,0\leqslant y \leqslant \Delta y$且$x,y$為整數
所以$x,y$的取值共有$\Delta x / a=\Delta y/b=gcd(\Delta x,\Delta y)$種
除去$x=\Delta x,y=\Delta y$這組解,這兩點連線上共有$gcd(\Delta x,\Delta y)-1$個整點。
接下來我們可以直接枚舉線段,然后計算有線段上有多少個整點;然而這樣復雜度是$O(n^2m^2)$的。
然后,顯然每一條線段經過平移,使它的左端點在矩形左下角或者左上角。由于向下和向上的線段對稱,所以只需要計算一種即可。
所以就固定一個端點為$(0,0)$,枚舉另外一個端點在哪里,計算一下即可。
下面貼代碼(話說這么一道題我好像講復雜了):
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)using namespace std; typedef long long llg;int n,m; llg ans,x;int gcd(int a,int b){if(!b) return a;int r=a%b;while(r) a=b,b=r,r=a%b;return b; }int main(){File("a");scanf("%d %d",&n,&m);x=(n+1)*(m+1); ans=x*(x-1)*(x-2)/6;for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)if(i|j){llg x=(llg)(n-i+1)*(llg)(m-j+1);ans-=x*(llg)(gcd(i,j)-1);if(i && j) ans-=x*(llg)(gcd(i,j)-1);}printf("%lld",ans);return 0; }轉載于:https://www.cnblogs.com/lcf-2000/p/6218327.html
總結
以上是生活随笔為你收集整理的BZOJ 3505 【CQOI2014】 数三角形的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机root不了的解决方法
- 下一篇: ITer必备数学思维——同济大学高等数学