杭電1575(矩陣快速冪模板)
阿新 • • 發佈:2018-12-16
Problem Description
A為一個方陣,加粗樣式則Tr A表示A的跡(就是主對角線上各項的和),現要求Tr(A^k)%9973。
Input
資料的第一行是一個T,表示有T組資料。 每組資料的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)兩個資料。接下來有n行,每行有n個數據,每個資料的範圍是[0,9],表示方陣A的內容。
Output
對應每組資料,輸出Tr(A^k)%9973。
Sample Input
2 2 2 1 0 0 1 3 99999999 1 2 3 4 5 6 7 8 9
Sample Output
2 2686
題意描述:
給你一個n(1<n<11)階方陣,讓你計算出它的k次方(不用輸出),並且最後輸出它主對角線的所有元素之和。 中間還有一個取模運算,意思是每次計算的值都要對9973進行取模,使它處於0~9972。
思想解析:
題目樣例中給了99999999次方,所以肯定不能直接去算,直接算肯定超時的,所以這就涉及到了快速冪的思想,可以這麼解釋:每個十進位制數都可以變換成二進位制,比如21,換成二進位制是10101,所以可以用右移的方法,來控制乘不乘。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Ride ///用結構體來存放矩陣比較方便 { int e[20][20]; }; int n; Ride ride(Ride a,Ride b) ///兩個矩陣相乘 { Ride c; memset(c.e,0,sizeof(c.e)); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) for(int k=1; k<=n; k++) c.e[i][j] = (c.e[i][j] + a.e[i][k] * b.e[k][j]) % 9973; return c; } int main() { Ride rec,ans; int t,k,sum; cin >> t; while(t--) { sum=0; scanf("%d %d",&n,&k); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) scanf("%d",&rec.e[i][j]); memset(ans.e,0,sizeof(ans.e));///將ans矩陣變成單位矩陣 for(int i=1; i<=n; i++) ans.e[i][i]=1; while(k) { if(k & 1) ///當k的最後一位是1時,ans*rec ans=ride(ans,rec); rec=ride(rec,rec);///每次迴圈 rec都要自乘 k >>= 1; ///k右移,相當於k/2 } // for(int i=1; i<=n; i++) ///輸出矩陣 // { // for(int j=1; j<=n; j++) // printf("%d ",ans.e[i][j]); // cout << endl; // } for(int i=1; i<=n; i++) ///計算對角線和 sum = (sum+ans.e[i][i]) % 9973; cout << sum % 9973 << endl; } return 0; }