题目链接:
http://poj.org/problem?id=3150
题意:
一个环上有n个数,定义一种操作将它和它距离小于d的数加和再模m。每次操作刷新所有数。问k次之后都将变成什么数?
思路:
http://blog.csdn.net/lin375691011/article/details/38493267
矩阵快速幂加速递推。
按照正常思路第i次操作是基于第i-1次操作完成的,也就是说要完成第i次操作需要先完成第i-1次。
但是用于矩阵之后可以直接推出第i次与第一次之间是什么关系。
这个矩阵是可以通过矩阵快速幂得出的。
如果你注意关系矩阵的建立的话,你会发现这么一个规律。对于d=1来说:
b^1 =
[1, 1, 0, 0, 1]
[1, 1, 1, 0, 0]
[0, 1, 1, 1, 0]
[0, 0, 1, 1, 1]
[1, 0, 0, 1, 1]
b^2 =
[3, 2, 1, 1, 2]
[2, 3, 2, 1, 1]
[1, 2, 3, 2, 1]
[1, 1, 2, 3, 2]
[2, 1, 1, 2, 3]
b^3 =
[7, 6, 4, 4, 6]
[6, 7, 6, 4, 4]
[4, 6, 7, 6, 4]
[4, 4, 6, 7, 6]
[6, 4, 4, 6, 7]
b^4 =
[19, 17, 14, 14, 17]
[17, 19, 17, 14, 14]
[14, 17, 19, 17, 14]
[14, 14, 17, 19, 17]
[17, 14, 14, 17, 19]
也就是说我们只需要存第一行就行了。每次矩阵乘法也只需要得出第一行就行了。
代码:
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 using namespace std; 6 typedef long long ll; 7 #define MS(a) memset(a,0,sizeof(a)) 8 #define MP make_pair 9 #define PB push_back 10 const int INF = 0x3f3f3f3f; 11 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 12 inline ll read(){ 13 ll x=0,f=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 ////////////////////////////////////////////////////////////////////////// 19 const int maxn = 1e5+10; 20 21 struct matrix{ 22 ll m[505]; 23 void clear(){ 24 MS(m); 25 } 26 }r,a,ans; 27 28 int n,mod,d,k; 29 30 matrix mul(matrix a,matrix b){ 31 matrix re; 32 re.clear(); 33 int p; 34 for(int i=0; i<n; i++){ 35 p = (n-i)%n; 36 for(int j=0; j<n; j++){ 37 re.m[i] = (re.m[i]+a.m[j]*b.m[p])%mod; 38 p = (p+1)%n; 39 } 40 } 41 return re; 42 } 43 44 matrix qpow(int k){ 45 matrix e; 46 e.clear(); 47 e.m[0] = 1; 48 while(k){ 49 if(k & 1) e = mul(e,a); 50 a = mul(a,a); 51 k >>= 1; 52 } 53 return e; 54 } 55 56 int main(){ 57 while(cin>>n>>mod>>d>>k){ 58 a.clear(); r.clear(); 59 for(int i=0; i<n; i++){ 60 r.m[i] = read(); 61 } 62 63 for(int i=0; i<n; i++){ 64 if(i<=d || (n-i)<=d) a.m[i] = 1; 65 else a.m[i] = 0; 66 } 67 68 a = qpow(k); 69 70 ans = mul(r,a); 71 72 for(int i=0; i<n; i++){ 73 if(i) printf(" "); 74 cout << ans.m[i]; 75 } 76 puts(""); 77 } 78 79 return 0; 80 }