zoukankan      html  css  js  c++  java
  • [TopCoder11557]MatrixPower

    vjudge

    description

    你有一个(n imes n)的矩阵(A),下标从(0)开始,其中(A_{i,j}=di + q^j)
    给你(d,q,n,k,s,t),求((A^k)_{s,t})的值模(10^9+7)
    (nle10^4,d,q,kle10^9,0le 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} imes sd+f_{i,1} imes ss\f_{i+1,1}=f_{i,0} imes n+f_{i,1} imes 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;
    	}
    };
    
  • 相关阅读:
    【BZOJ】【2661】【Beijing WC2012】连连看
    【BZOJ】【2424】【HAOI2010】订货
    【BZOJ】【1061】【NOI2008】志愿者招募
    【POJ】【3680】Intervals
    网络流建模
    【BZOJ】【1221】【HNOI2001】软件开发
    【BZOJ】【1877】【SDOI2009】晨跑
    bzoj2054: 疯狂的馒头(并查集)
    浴谷金秋线上集训营 T11738 伪神(树链剖分)
    51nod1967 路径定向(欧拉回路+结论题)
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9386135.html
Copyright © 2011-2022 走看看