先上题 : C-小红的二叉树_牛客周赛 Round 79
题目看起来 很吓人 ,其实就是纸老虎 罢了 !!!
这种题目 一看就是找规律 求通项公式 或者递推 。
思路 :
我会选择先找 递推公式 :(这是数学的叫法 , 我们叫他为状态转移方程) 为什么我不先去找通项公式呢? 显然找递推公式 比通项公式容易得多 ! 因为 你只需要关注与当前步和下一步 的转移 关系 ! ! 而不需要关注全局 ,况且有了递推公式之后可能可以最终化成通项公式,当然 这就考验你的数学功底 了 (你的数学工具够不够强大 )
显然 (从第3层开始 ) 每一层比上一层 多了 pow( 2 , n-1 ) +pow( 2 ,n-2 )
推导 :
为了求解通项 f(n),我们从给定的递推关系式开始:
f(n)−f(n−1)=2n−1+2n−2
首先,我们简化等式右边的表达式:
2n−1+2n−2=2n−2(2+1)=3⋅2n−2
所以,递推关系式变为:
f(n)−f(n−1)=3⋅2n−2
为了找到 f(n),我们需要对这个递推关系式进行求和。我们从 n=3 开始,一直加到 n:
f(3)−f(2)=3⋅23−2=3⋅21=6 f(4)−f(3)=3⋅24−2=3⋅22=12 f(5)−f(4)=3⋅25−2=3⋅23=24 ⋮ f(n)−f(n−1)=3⋅2n−2
将这些等式相加,我们得到:
f(n)−f(2)=3(21+22+23+⋯+2n−2)
等式右边是一个等比数列的和,首项为 21=2,公比为 2,项数为 n−2。
我们得到:
所以,最终的通项公式为:
3 *pow( 2 ,n-1 )−5
做法 :
1 . 递推 ( 使用快速幂 ) O( n *log( n ) )
2. 通项公式 (快速幂 ) O ( 1 ) / O ( log n )
C++ACcode 1:
#include<bits/stdc++.h> #define int long long using namespace std; int h; const int p=1e9+7; signed main() { ios::sync_with_stdio(0),cin.tie(0); cin>>h; vector<int> f(h+100); f[1]=0; f[2]=1; auto qpower = [&] (int a,int b){ int res=1; while(b){ if(b&1){ res=(res*a)%p; } b>>=1; a=(a*a)%p; } return res; }; if(h==1){ cout<<"0"<<'\n'; return 0; } if(h==2){ cout<<"1"<<'\n'; return 0; } for(int i=3;i<=h;++i){ f[i]=((f[i-1])%p+(qpower(2,i-1))%p+(qpower(2,i-2))%p)%p; } cout<<f[h]<<'\n';
C++ACcode 2 :
#include<bits/stdc++.h> #define int long long using namespace std; int n; const int p = 1e9+7; signed main() { ios::sync_with_stdio(0),cin.tie(0); cin>>n; auto qpower = [&](int a,int b){ int res=1; while(b){ if(b&1){ res=(res*a)%p; } b>>=1; a=(a*a)%p; } return res; }; if(n==1){ cout<<"0"<<'\n'; return 0; } else if(n==2){ cout<<"1"<<'\n'; return 0; } cout<<(3*qpower(2,n-1)%p-5)%p<<'\n'; return 0; }