Where a, b, n, m are positive integers.┌x┐is the ceil of x. For example, ┌3.14┐=4. You are to calculate S n.
You, a top coder, say: So easy!
2 3 1 2013 2 3 2 2013 2 2 1 2013
4 144
这道题目大意是给你a,b,n,m,算出上面那个式子的值,由于数值较大,所以不可能是暴力。
可以算得Sn=(a+sqrt(b))^n=Xn+Yn*sqrt(b);(Xn,Yn是未知数,但一定是实数),
Sn+1=X(n+1)+Y(n+1)*sqrt(b)=(Xn+Yn*sqrt(b))*(a+sqrt(b));
可得X(n+1)=(a*Xn+b*Yn);
Y(n+1)=(a*Yn+Xn);
构造矩阵为
再根据a,b 的范围,0<(a-sqrt(b))<1;所以(a+sqrt(b))^n向上取整就是(a+sqrt(b))^n+(a-sqrt(b))^n;
同理(a-sqrt(b))^n=Xn-Yn*sqrt(b);所以相加得Xn*2,所以最后向上取整的值就是(Xn*2)
答案为(Xn*2)%m;
一下为借鉴代码
#include <iostream> #include <cstring> using namespace std; typedef long long ll; ll m; struct matrix { ll f[2][2]; }; matrix mul(matrix a,matrix b) { matrix ans; memset(ans.f,0,sizeof(ans.f)); for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { for(int k=0; k<2; k++) { ans.f[i][j]=(ans.f[i][j]+a.f[i][k]*b.f[k][j])%m; } } } return ans; } matrix pow(matrix a, int p) { matrix res; memset(res.f,0,sizeof(res.f)); for(int i=0; i<2; i++) res.f[i][i]=1; while(p) { //cout<<"___"<<endl; if(p&1) res=mul(res,a); p>>=1; a=mul(a,a); } return res; } int main() { ll a,b,n; matrix ma,ab; while(cin>>a>>b>>n>>m) { ma.f[0][0]=a; ma.f[0][1]=b; ma.f[1][0]=1; ma.f[1][1]=a; ab=pow(ma,n); ll ss=ab.f[0][0]; cout<<(ss*2+m)%m<<endl; } return 0; }
根据共轭的另一种做法
Cn+1=(a+sqrt(b))^n*(a+sqrt(b))+(a-sqrt(b))^n*(a-sqrt(b))Cn-1*(a*a-b)=(a+sqrt(b))^n*(a-sqrt(b))+(a-sqrt(b))^n*(a+sqrt(b))加减消去根号项得到:Cn+1=2*a*Cn+(b-a*a)*Cn-1,公式化简完毕,2*2阶矩阵可以直接写了
|2*a b-a*a| | Cn | | Cn+1|
|1 0 |* | Cn-1|= | Cn |同样是快速幂 只不过矩阵不同,便没有代码了