[TopCoder11557]MatrixPower

vjudge

description

你有一个\(n \times n\)的矩阵\(A\),下标从\(0\)开始,其中\(A_{i,j}=di + q^j\)
给你\(d,q,n,k,s,t\),求\((A^k)_{s,t}\)的值模\(10^9+7\)
\(n\le10^4,d,q,k\le10^9,0\le s,t <n\)

sol

先写出一个极其丑陋的柿子:

\[(A^k)_{s,t}=\sum_{x_1}\sum_{x_2}...\sum_{x_{k-1}}(ds+q^{x_1})(dx_1+q^{x_2})...(dx_{k-1}+q^t) \]

等于你从\(s\)出发走\(k\)次走到\(t\),那么中间就有\(k-1\)个位置可以任选,所以才会有前面的\(k-1\)\(\sum\)
把后面的括号暴力展开,一共有\(2^k\)项。然而还是做不了。
考虑每个\(x_i\)。它出现在答案中的形式只有\(4\)种:\(1,dx_i,q_{x_i},dx_iq^{x_i}\)。这取决于这个\(x_i\)出现的两个相邻的括号内取的是哪一个。
预处理出\(sd=\sum_{i=0}^{n-1}di,sq=\sum_{i=0}^{n-1}q^i,ss=\sum_{i=0}^{n-1}diq^i\)
\(f_{i,0/1}\)表示考虑了前\(i\)个括号,第\(i\)个括号取的是前一项/后一项时,只计算前\(i-1\)\(x_i\)时的答案。显然有转移式:

\[f_{i+1,0}=f_{i,0}\times sd+f_{i,1}\times ss\\f_{i+1,1}=f_{i,0}\times n+f_{i,1}\times sq \]

初值\(f_{1,0}=ds,f_{1,1}=1\)。最后一次转移特判一下(因为最后一个\(x\)必须强制为\(t\))。
这样就可以做\(O(k)\)\(dp\)了。考虑到每次的转移都是一样的,所以直接矩乘就好了。

code

为什么没有人告诉我,定义在\(\mbox{class}\)里面的变量的初值不是\(0\)
害我浪费了宝贵的\(\mbox{20min}\)才发现这个错误\(\mbox{qwq}\)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 10005;
const int mod = 1e9+7;
int fastpow(int a,int b){
	int s=1;
	while (b) {if (b&1) s=1ll*s*a%mod;a=1ll*a*a%mod;b>>=1;}
	return s;
}
struct matrix{
	int a[2][2];
	matrix(){memset(a,0,sizeof(a));}
	matrix(int q,int w,int d,int b){
		a[0][0]=q;a[0][1]=w;a[1][0]=d;a[1][1]=b;
	}
	int* operator [](int x){return a[x];}
	matrix operator * (matrix &b){
		matrix c;
		for (int i=0;i<2;++i)
			for (int j=0;j<2;++j)
				for (int k=0;k<2;++k)
					c[i][k]=(1ll*a[i][j]*b[j][k]+c[i][k])%mod;
		return c;
	}
}S,T,A,B;
class MatrixPower{
public:
	int m,sd,sq,ss;vector<int>ans;
	vector<int> getElements(int d,int q,int n,int k,vector<int>r,vector<int>c){
		m=r.size();ans.resize(m);
		if (k==1){
			for (int i=0;i<m;++i) ans[i]=(1ll*d*r[i]+fastpow(q,c[i]))%mod;
			return ans;
		}
		k-=2;sd=sq=ss=0;
		for (int i=0;i<n;++i) sd=(sd+1ll*d*i)%mod;
		for (int i=0;i<n;++i) sq=(sq+fastpow(q,i))%mod;
		for (int i=0;i<n;++i) ss=(ss+1ll*d*i%mod*fastpow(q,i))%mod;
		T=matrix(sd,n,ss,sq);S=matrix(1,0,0,1);
		while (k) {if (k&1) S=S*T;T=T*T;k>>=1;}
		for (int i=0;i<m;++i){
			A=matrix(1ll*d*r[i]%mod,1,0,0);
			B=matrix(sd,1ll*n*fastpow(q,c[i])%mod,ss,1ll*sq*fastpow(q,c[i])%mod);
			A=A*S*B;
			ans[i]=(1ll*A[0][0]+A[0][1]+A[1][0]+A[1][1])%mod;
		}
		return ans;
	}
};
posted @ 2018-07-29 18:01  租酥雨  阅读(185)  评论(0编辑  收藏  举报