|
這題對(duì)我來(lái)說(shuō)太難啦,看了報(bào)告半天才弄明白是咋回事。 高手們的解題報(bào)告相當(dāng)飄逸。我來(lái)寫一個(gè)造福菜鳥的。 首先來(lái)看一下Sample里的第一組數(shù)據(jù)。 1 2 2 1 2 經(jīng)過(guò)一次變換之后就成了 5 5 5 5 4 它的原理就是 a0 a1 a2 a3 a4 -> (a4+a0+a1) (a0+a1+a2) (a1+a2+a3) (a2+a3+a4) (a3+a4+a0) 如果用矩陣相乘來(lái)描述,那就可以表述為1xN和NxN的矩陣相乘,結(jié)果仍為1xN矩陣 a = 1 2 2 1 2 b = 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 a * b = 5 5 5 5 4 所以最終結(jié)果就是:a * (b^k) 線性代數(shù)不合格的同鞋表示壓力很大。。 對(duì)一個(gè)NxN矩陣求k次方,而且這個(gè)k很大,N也不小,怎么辦? 所以有高手觀察到了,這個(gè)矩陣長(zhǎng)得有點(diǎn)特殊,可以找到一些規(guī)律: 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] 發(fā)現(xiàn)神馬沒(méi)有。就是無(wú)論是b的幾次冪,都符合A[i][j] = A[i-1][j-1]
高手說(shuō)是這樣推倒出來(lái)地: ““”
利用矩陣A,B具有a[i][j]=A[i-1][j-1],B[i][j]=B[i-1][j-1](i-1<0則表示i-1+n,j-1<0則表示j-1+n)
我們可以得出矩陣C=a*b也具有這個(gè)性質(zhì)
C[i][j]=sum(A[i][t]*B[t][j])=sum(A[i-1][t-1],B[t-1][j-1])=sum(A[i-1][t],B[t][j-1])=C[i-1][j-1]
“”“ 這樣就可以開(kāi)一個(gè)N大小的數(shù)組來(lái)存放每次計(jì)算的結(jié)果了。而沒(méi)必要用NxN。 N的問(wèn)題解決了,但是k還是很大,怎么辦? 這時(shí)候可以用二分法來(lái)求b^k b^k = b^1 * b^4 * b^16 。。。 計(jì)算過(guò)程中,必定會(huì)出現(xiàn)數(shù)字大于M的情況。 切記 x*y = (x%M)*(y%M) 最后,經(jīng)過(guò)多次優(yōu)化,這題的代碼居然被高手寫成了如下的一小坨,實(shí)在是。。給力哇
#include<iostream> using namespace std; int n,m,d,k; void mul(long long a[],long long b[]) { int i,j; long long c[501]; for(i=0;i<n;++i)for(c[i]=j=0;j<n;++j)c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)]; for(i=0;i<n;b[i]=c[i++]%m); } long long init[501],tmp[501]; int main() { int i,j; scanf("%d%d%d%d",&n,&m,&d,&k); for(i=0;i<n;++i)scanf("%I64d",&init[i]); for(tmp[0]=i=1;i<=d;++i)tmp[i]=tmp[n-i]=1; while(k) { if(k&1)mul(tmp,init); mul(tmp,tmp); k>>=1; } for(i=0;i<n;++i)if(i)printf(" %I64d",init[i]);else printf("%I64d",init[i]); printf("\n"); return 0; }
|