zoukankan      html  css  js  c++  java
  • CodeForces 575A

    集训队作业哦。

    粉兔:“矩阵快速幂 sb 题。”

    洛谷题目页面传送门 & CF 题目页面传送门

    题意见洛谷。

    一脸的矩阵,用矩阵把递推式表示出来:

    [egin{bmatrix}f_i&f_{i+1}end{bmatrix}Delta_i=egin{bmatrix}f_{i+1}&f_{i+2}end{bmatrix} ]

    其中

    [Delta_i=egin{bmatrix}0&s_i\1&s_{i+1}end{bmatrix} ]

    那么答案就是

    [left(egin{bmatrix}f_0 & f_1end{bmatrix}prod_{i=0}^{k-1}Delta_i ight)_{1,1}=left(prod_{i=0}^{k-1}Delta_i ight)_{2,1} ]

    只需要求那个 (prod) 即可。

    注意到 (s) 是有周期性的,(n) 个一周期。先不考虑有 (m) 个特殊点,这样显然可以算出 (n) 个的积,然后快速幂。

    如果有 (m) 个特殊点呢?考虑在有特殊点处分段,有特殊点的周期们特殊算,无特殊点的周期段们快速幂。周期段数显然是 (mathrm O(m)) 的,那么快速幂部分就是 (mathrm O(mlog))

    如何快速维护特殊算部分呢?考虑在原 (n) 个矩阵的乘积上修改,注意到一个特殊的 (s_i) 只会影响 (Delta_i)(Delta_{i-1})。但是矩阵乘法没有逆运算,不能直接除或 BIT;需要修改,也不能倍增。可以用线段树维护,单点修改,整体查积,每个有特殊点的周期算完就改回去。

    时间复杂度 (mathrm O(n+mlog))

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define mp make_pair
    #define X first
    #define Y second
    #define pb push_back
    #define int long long
    const int inf=0x3f3f3f3f3f3f3f3f;
    const int N=50000,M=50000;
    int k,mod;
    int n;
    int s[N];
    int m;
    pair<int,int> v[M+1];
    vector<pair<int,pair<bool,int> > > v0;
    struct matrix{//矩阵 
    	int a[2][2];
    	int *operator[](int x){return a[x];}
    	matrix(int x=0,int y=0,int z=0,int xx=0){
    		a[0][0]=x,a[0][1]=y,a[1][0]=z,a[1][1]=xx;
    	}
    	friend matrix operator*(matrix x,matrix y){
    		return matrix((x[0][0]*y[0][0]+x[0][1]*y[1][0])%mod,
    		              (x[0][0]*y[0][1]+x[0][1]*y[1][1])%mod,
    		              (x[1][0]*y[0][0]+x[1][1]*y[1][0])%mod,
    		              (x[1][0]*y[0][1]+x[1][1]*y[1][1])%mod);
    	}
    	void prt(){printf("%lld %lld
    %lld %lld
    ",a[0][0],a[0][1],a[1][0],a[1][1]);}
    };
    matrix qpow(matrix x,int y){//快速幂 
    	matrix res(1,0,0,1);
    	while(y){
    		if(y&1)res=res*x;
    		x=x*x;
    		y>>=1;
    	}
    	return res;
    }
    struct segtree{//线段树 
    	struct node{int l,r;matrix v;}nd[N<<2];
    	#define l(p) nd[p].l
    	#define r(p) nd[p].r
    	#define v(p) nd[p].v
    	void sprup(int p){v(p)=v(p<<1)*v(p<<1|1);}
    	void bld(int l=0,int r=n-1,int p=1){
    		l(p)=l;r(p)=r;
    		if(l==r)return v(p)=matrix(0,s[l],1,s[(l+1)%n]),void();
    		int mid=l+r>>1;
    		bld(l,mid,p<<1);bld(mid+1,r,p<<1|1);
    		sprup(p);
    	}
    	void init(){bld();}
    	void chg(int x,bool y,int v,int p=1){
    		if(l(p)==r(p))return v(p)[y][1]=v,void();
    		int mid=l(p)+r(p)>>1;
    		chg(x,y,v,p<<1|(x>mid));
    		sprup(p);
    	}
    	matrix prod(int l=0,int r=n-1,int p=1){
    		if(l>r)return matrix(1,0,0,1);
    		if(l<=l(p)&&r>=r(p))return v(p);
    		int mid=l(p)+r(p)>>1;
    		matrix res(1,0,0,1);
    		if(l<=mid)res=res*prod(l,r,p<<1);
    		if(r>mid)res=res*prod(l,r,p<<1|1);
    		return res;
    	}
    }segt;
    signed main(){
    	cin>>k>>mod;
    	cin>>n;
    	for(int i=0;i<n;i++)cin>>s[i];
    	cin>>m;
    	for(int i=1;i<=m;i++)cin>>v[i].X>>v[i].Y;
    	v0.pb(mp(-n,mp(0,0)));v0.pb(mp(inf,mp(0,0)));
    	for(int i=1;i<=m;i++){
    		v0.pb(mp(v[i].X,mp(0,v[i].Y)));
    		if(v[i].X)v0.pb(mp(v[i].X-1,mp(1,v[i].Y)));
    	}
    	sort(v0.begin(),v0.end());
    	segt.init();
    	matrix res(1,0,0,1);
    	int las=0;
    	for(int i=1,ie;i<v0.size();i=ie+1){
    		ie=i;while(ie+1<v0.size()&&v0[ie+1].X/n==v0[i].X/n)ie++;
    		if(v0[i].X/n>=k/n){las=v0[i-1].X/n;break;}
    		res=res*qpow(segt.prod(),v0[i].X/n-1-v0[i-1].X/n);
    		for(int j=i;j<=ie;j++)segt.chg(v0[j].X%n,v0[j].Y.X,v0[j].Y.Y);//修改 
    		res=res*segt.prod();
    		for(int j=i;j<=ie;j++)segt.chg(v0[j].X%n,v0[j].Y.X,v0[j].Y.X?s[(v0[j].X+1)%n]:s[v0[j].X%n]);//改回去 
    	}
    	res=res*qpow(segt.prod(),k/n-1-las);
    	for(int i=0;i<v0.size();i++)if(v0[i].X/n==k/n)segt.chg(v0[i].X%n,v0[i].Y.X,v0[i].Y.Y);
    	res=res*segt.prod(0,k%n-1);
    	cout<<res[1][0];
    	return 0;
    }
    
    珍爱生命,远离抄袭!
  • 相关阅读:
    eclipse最有用快捷键整理(转)
    Spring IOC的配置使用(转)
    char varchar varchar2 的区别 (转)
    BigDecimal用法详解(转)
    20160126--springaop
    20160125--Spring
    20150122--接口
    Servlet与JSP的区别
    练习
    151127
  • 原文地址:https://www.cnblogs.com/ycx-akioi/p/CodeForces-575A.html
Copyright © 2011-2022 走看看