2013 ACM/ICPC 長沙賽區湖大全國邀請賽 A題(6.1修訂)
阿新 • • 發佈:2019-01-10
小記:這次大賽教訓慘重,ACM的路任重道遠,現在努力做出每道題的解題報告吧。以此來撫慰我那慘痛的心靈。
題目:
這個題目名叫So easy! 當初看了 就想A, 現在看來這估計就是個陷阱,數學不好的必被坑。
由於我是用word寫好的,但是裡面的數學符號複製不出來,所以我就用圖片來描述好了。
Solution
遞推求通項公式的特徵根的方法可以看這個:
(之前沒A之前,犯了右乘和左乘的理解錯誤,改過來就差不多了,之前的程式碼提交的錯了,除了左乘和右乘理解錯誤外,還有就是沒有將進行快速冪的矩陣裡的負元素變成正數(通過加M,即要取模的值變成正數,如果有負數的話,進行快速冪是錯的),全改了之後就A了。)(6.1 修改)
在快速冪的時候就進行取模運算,防溢位。
進過轉換之後,我們發現這題純粹就是一道簡單的矩陣快速冪的模板題。頓時覺得數學是門非常深奧的課程,需要不斷的去學習探索。敗在這題之下,確實只能怪自己基礎不扎
實,受教了。模板我的部落格裡有。
這題,經過幾天的思考,在wuzhengkai大神的點撥下,以及另一位神犇(連結沒找到)的幫助下,頓悟了。在此特地感謝!
//下面貼上我的程式碼,湖大OJ 暫時打不開,所以還不知道正確與否,不過根據我自己生成的隨機資料,理論上應該沒錯。
下面是錯誤的程式碼:
#include <iostream> #include <stdio.h> using namespace std; #define N 2 #define ll unsigned long long struct Matrix { ll v[N][N]; }; Matrix A,B={1,0,0,1}; ll M; Matrix mul(Matrix m1,Matrix m2,ll M){ int i,j,k; Matrix c; for(i=0;i<N;i++)for(j=0;j<N;j++){ c.v[i][j]=0; for(k=0;k<N;k++) c.v[i][j]+=(m1.v[i][k]*m2.v[k][j])%M; c.v[i][j] %= M; } return c; } Matrix Mpow(Matrix A,Matrix B,ll n,ll M){ Matrix x=A,c=B; while(n>=1){ if(n&1)c=mul(c,x,M); n>>=1; x=mul(x,x,M); } return c; } int main() { //freopen("d:\\in.txt","r",stdin); //freopen("d:\\out.txt","w",stdout); //int flag = 0; ll n, a, b; while(cin>>a>>b>>n>>M){ /*if(flag)cout << endl; else flag = 1;*/ if(n == 1){ cout << (2*a) % M <<endl;continue; } if(n == 2){ cout << (2*a*a + 2*b) % M <<endl;continue; } A.v[0][0] = 2*a; A.v[0][1] = b - a*a ; A.v[1][0] = 1; A.v[1][1] = 0; Matrix p = Mpow(A,B,n-2,M), q = {2*a*a + 2*b, 0, 2*a, 0}; p = mul(p,q,M); cout<<p.v[0][0]<<endl; } return 0; }
改正後的A過的程式碼:(6.1修改)
#include <iostream> #include <stdio.h> using namespace std; #define N 2 #define ll long long struct Matrix { ll v[N][N]; }; Matrix A,B={1L,0L,0L,1L}; ll M; Matrix mul(Matrix m1,Matrix m2,ll M){ int i,j,k; Matrix c; for(i = 0; i < N; i++) for(j = 0; j < N; j++){ c.v[i][j] = 0; for(k = 0; k < N; k++){ c.v[i][j] += (m1.v[i][k]*m2.v[k][j])%M; c.v[i][j] %= M; } c.v[i][j] %= M; } return c; } Matrix Mpow(Matrix A,Matrix B,ll n,ll M){ Matrix x = A,c = B; while(n >= 1){ if(n&1L)c = mul(c,x,M); n >>= 1; x = mul(x,x,M); } return c; } int main() { //freopen("F:\\problem A\\in.txt","r",stdin); //freopen("F:\\problem A\\out.txt","w",stdout); ll n, a, b, t; while(cin>>a>>b>>n>>M){ if(n == 1){ cout << (2*(a%M)) % M <<endl;continue; } if(n == 2){ cout << ((2*((a%M)*(a%M))%M)%M + (2*b)%M) % M <<endl;continue; } A.v[0][0] = (2*(a%M)) % M; t = a; t *= a; A.v[0][1] = 1; t = b - t; while(t < 0)t += M; A.v[1][0] = t; A.v[1][1] = 0; Matrix p = Mpow(A,B,n-2,M), q = {((2*((a%M)*(a%M))%M)%M + (2*b)%M) % M, (2*(a%M)) % M, 0L, 0L}; p = mul(q,p,M); cout<<p.v[0][0]<<endl; } return 0; }