HDU - 4565 So Easy!(共轭构造+推公式+矩阵快速幂)
生活随笔
收集整理的這篇文章主要介紹了
HDU - 4565 So Easy!(共轭构造+推公式+矩阵快速幂)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題意:給出a,b,m,n,求
解析:題意一目了然,此題的關鍵是推出解決問題的公式。
首先,題目要求括號內n次方后向上取整再模m,而這里給到的a與b的關系接下來也會用到:<b<
我們按照共軛構造的形式,構造出=,=
再設=+,由于共軛的性質,易知為整數,又因為<b<,得到0<<1,所以0<<1,題目中要求的向上取整所得的整數即為
此時已經將題目轉化為了求對m取余的結果了,接下來就應該著手求Cn的表達式了,我們要盡可能使用假設的共軛關系:
即+=(A+B)(A-B),開始推導:
首先=+
上面兩個式子作差,可以再將Cn帶入,可以直接推得
=2*a*+(b-)*
即
=2*a*+(b-)*
這個時候就可以構造矩陣了
然后直接矩陣快速冪就可以解決問題了。
注意:(b-)可能是負數,所以快速冪在處理的時候需要先加再模,注意對負數的處理。
上代碼:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<sstream> #include<cmath> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2;LL mod;struct M {LL a[N][N]; };M operator*(M a,M b) {M temp;memset(temp.a,0,sizeof(temp.a));for(LL i=0;i<N;i++)for(LL j=0;j<N;j++){temp.a[i][j]=0;for(LL k=0;k<N;k++){temp.a[i][j]=(temp.a[i][j]+((a.a[i][k]*b.a[k][j])%mod+mod)%mod)%mod;}}return temp; } M q_pow(M a,LL n) {M ans;memset(ans.a,0,sizeof(ans.a));for(LL i=0;i<N;i++)ans.a[i][i]=1;while(n){if(n&1)ans=ans*a;a=a*a;n>>=1;}return ans; }int main() { // freopen("input.txt","r",stdin);LL a,b,m,n;while(scanf("%lld%lld%lld%lld",&a,&b,&n,&m)!=EOF){if(n==1){cout<<2*a%m<<endl;continue;}mod=m;M start;start.a[1][1]=0;start.a[0][0]=2*a;start.a[1][0]=b-a*a;start.a[0][1]=1;M ans;memset(ans.a,0,sizeof(ans.a));ans.a[0][0]=2*a;ans.a[0][1]=2;M res=q_pow(start,n-1);cout<<((ans*res).a[0][0]+mod)%mod<<endl; /* M temp=q_pow(start,2);temp=ans*temp;for(int i=0;i<N;i++){for(int j=0;j<N;j++)cout<<temp.a[i][j]<<' ';cout<<endl;}*/}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 4565 So Easy!(共轭构造+推公式+矩阵快速幂)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZOJ - 2972 Hurdles o
- 下一篇: HDU - 5451 Best Solv