[CQOI2014]数三角形 组合数 + 容斥 + gcd
生活随笔
收集整理的這篇文章主要介紹了
[CQOI2014]数三角形 组合数 + 容斥 + gcd
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
推導過程 : 組合數+容斥原理+gcd
正確做法是暴力的一種優化,ans=所有情況 - 平行坐標軸的三點共線 - 斜線三點共線
如果快速求斜線三點共線:
首先要知道一個結論,對于點(a,b) (x,y)連成的線段而言(其中a>x,b>y),
在它們中間有gcd(a-x,b-x)-1個整點,因此基本的思路就是枚舉兩個點,
然后第3個點就是gcd(a-x,b-x)-1種可能了
至于為什么第3個點一定要在中間,是為了保證不重不漏,只用兩邊的點統計中間的點,
然而這樣復雜度太高,于是可以發現,可以將這兩個點組成的線段中左下那個端點平移至原點,
這樣相當于只要枚舉一個點,并且由于要考慮k<0的情況,因為矩形是有對稱性的,
所以要求原點+一個點 與 (0,m)+一個點 的和就可以直接2 *(原點+一個點)
由于長的一樣的線有很多,于是問題就轉化為如果求這些一樣的線的個數,
那么可以發現,這樣任意一條線,向上只能平移(n - i),向下(m - j)次,
所以可能性就為(n - i + 1) * (m - j + 1),其中+1是因為可以向上移動0個單位
但由于這里n,m一開始就加了1,所以這個式子就不用+1了
因此枚舉每個點即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define LL long long 5 LL n,m,ans,go; 6 7 int gcd(int x,int y) 8 { 9 if(!y) return x; 10 else return gcd(y,x%y); 11 } 12 13 void work() 14 { 15 scanf("%lld%lld",&n,&m); 16 ++n,++m;//因為是一個網格,所以真正的坐標系其實有(n+1,m+1) 17 go=n*m; 18 ans=go * (go - 1) * (go - 2) / 6 - n * m * (m - 1) * (m - 2) / 6 - m * n * (n - 1) * (n - 2) / 6;//記得除掉取出數列的全排列 19 for(R i=1; i<n ;i++)//因為是取了原點,所以相當于坐標系是從0開始了 20 for(R j=1; j<m ;j++)//枚舉這個點 21 ans-=(LL)2 * (LL)(gcd(i,j) - 1) * (LL)(n - i) * (LL)(m - j); 22 printf("%lld\n",ans); 23 } 24 25 int main() 26 { 27 freopen("in.in","r",stdin); 28 work(); 29 fclose(stdin); 30 return 0; 31 }
?
轉載于:https://www.cnblogs.com/ww3113306/p/8762942.html
總結
以上是生活随笔為你收集整理的[CQOI2014]数三角形 组合数 + 容斥 + gcd的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tensorflow学习笔记————分类
- 下一篇: hashlib模式和hmac模式