2020牛客寒假演算法訓練營第一場題解(持續更新中)
這一題要求計算格點圖中”好三角形“的數量。好三角形是面積為1,至少有一條邊平行於x軸或y軸,並且頂點都在格點上的三角形。
那麼我們可以分兩種情況考慮,分別為同時平行於x軸和y軸以及只有一條邊平行。
第一種情況很簡單,在每個1*3的矩形中都有4個,那麼在n*m的矩形中一共有(m-2)*(n-1)+(n-2)*(m-1)種這樣的不同矩形,所以就有((m-2)*(n-1)+(n-2)*(m-1))*4個矩形。
第二種情況又可以分為兩種情況,分別為底為2高為1和底為1高為2兩種情況。
以底為2高為1為例,設x軸為m,y軸為n,這裡需要注意的就是不要與第一種情況重複。
如果底與x軸平行,我們可以得到(m-2)*n個不同的底,對於每個底來說,只需要選擇第三個點即可,因為第三個點選擇的時候不能構成直角三角形,否則會重複,所以對於每一個底,只能選擇(m-2)個點作為其頂點,然後對於每一行來說,都可以往上取或者往下取,但是由於最下面一行只能往上取和最上面一行只能往下取,所以我們把這兩行合併,最後就得到這樣的三角形有((m-2)*(m-2)*(n-1))*2個,那麼以y軸為底就有((n-2)*(n-2)*(m-1))*2個。
同理可得,以底為1的三角形分別有((m-1)*(m-2)*(n-2))*2和((n-1)*(n-2)*(m-2))*2個。最後只要把這5種全部加起來就行了。
在這裡我犯了一個非常低階的錯誤,那就是取模。寫這個題解也就是要提醒自己以後不要犯一樣的錯誤。下面是錯誤示範
ll ans=0; ans+=((m-2)*(n-1)+(n-2)*(m-1))*4%mod; ans+=((m-2)*(m-2)*(n-1))*2%mod; ans+=((n-2)*(n-2)*(m-1))*2%mod; ans+=((m-1)*(m-2)*(n-2))*2%mod; ans+=((n-1)*(n-2)*(m-2))*2%mod; cout<<ans%mod<<endl;View Code
一定要記得,取模一定要對每一個元素都要取模!!!!以下為AC程式碼
#include <iostream> using namespace std; #define ll long long ll mod=1000000007; int main() { ll n,m; cin>>n>>m; ll ans=0; ans+=(((m-2)%mod*(n-1))%mod+((n-2)*(m-1)%mod))*4%mod; ans+=((m-2)%mod*(m-2)%mod*(n-1)%mod)*2%mod; ans+=((n-2)%mod*(n-2)%mod*(m-1)%mod)*2%mod; ans+=((m-1)%mod*(m-2)%mod*(n-2)%mod)*2%mod; ans+=((n-1)%mod*(n-2)%mod*(m-2)%mod)*2%mod; ans%=mod; cout<<ans<<endl; return 0; }View Code
一個算數學期望的水題,知道數學期望就能做,就直接上程式碼了
#include<iostream> int main() { double n,x,a,b; scanf("%lf%lf%lf%lf",&n,&x,&a,&b); printf("%.2f",n*((x/100.00)*a+(1-x/100.00)*b)); }View Code
這個題是一個不是很明顯的矩陣快速冪,關於矩陣快速冪的問題我在別的部落格已經講過,這裡就不講,我們可以看到給的遞推式為
由於ab是一個常數,我們把這個常數設為t,那麼我們首先寫一下前幾項,可以很輕易的得到
f(1)=x f(2)=y f(3)=xyt f(4)=xy2t2 f(5)=x2y3t4 f(6)=x3y5t7 f(7)=x5y8t12
然後我們分別看x,y以及t的係數,我們看到他們的係數隨著n的變換形成的是斐波那契額數列,如果我們把斐波那契額的第n項設為feb(n)的話
那麼我們可以得到f(n)的表示式為
f(n)=xfeb(n-2)yfeb(n-1)t(feb(n-2)+feb(n-1)-1)
由於x,y,t均為常數,所以要想求f(n),我們只需要求出斐波那契的數列的第n-1項和第n-2項即可。
求斐波那契的第n項是個非常經典的矩陣快速冪,我們只要設矩陣為
1 1 2 1 3 2 5 3
1 0 那麼對其2次方為 1 1 三次方為 2 1 四次方為 3 2
根據矩陣快速冪我們可以很快的得到,但是這裡還有一點就是要利用費馬小定理