zoukankan      html  css  js  c++  java
  • 【[NOI2013]矩阵游戏】

    我们看到了及其可怕的数据范围

    这个样子都没有办法直接读入的数据范围应该怎么算

    我们观察一下递推式(f[i][j]=a*f[i][j]+b(j!=1))

    (f[i][1]=c*f[i-1][m]+d)

    转移非常简单,于是可以考虑一下矩阵乘法

    如果我们将这个矩阵破坏成一个链,那么就会有这种形式的递推

    连续推(m)次第一个柿子,之后再推一次第二个柿子,之后反复

    重复上面的过程(n)次就好了

    于是我们可以将连续转移(m)次一式的到的矩阵和第二个式子的转移矩阵乘起来,之后将这个矩阵再转移(n)次就是答案了

    由于(n,m)是在太大了,我们又发现模数是质数,于是我们可以利用费马小定理来降幂

    则有

    [A^{mod-1}\%mod=1 ]

    所以

    [A^mequiv A^{m\%(mod-1)}(\% mod ) ]

    至于为什么要特判(a=1)

    我怎么知道啊

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 5
    #define LL long long
    const LL mod=1000000007;
    char N_[1000005],M_[1000005];
    LL n,m,a,b,c,d;
    inline LL read()
    {
    	char c=getchar();
    	LL x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9')
    	  x=x*10%(mod-1)+c-48,c=getchar();
    	return x;
    }
    struct Mat
    {
    	LL a[4][4],ans[4][4];
    	inline void did_ans()
    	{
    		LL mid[4][4];
    		for(re int i=1;i<=2;i++)
    			for(re int j=1;j<=2;j++)
    				mid[i][j]=ans[i][j],ans[i][j]=0;
    		for(re int i=1;i<=2;i++)
    			for(re int j=1;j<=2;j++)
    				for(re int p=1;p<=2;p++)
    					ans[i][j]=(ans[i][j]+(a[i][p]*mid[p][j])%mod)%mod;
    	}
    	inline void did_a()
    	{
    		LL mid[4][4];
    		for(re int i=1;i<=2;i++)
    			for(re int j=1;j<=2;j++)
    				mid[i][j]=a[i][j],a[i][j]=0;
    		for(re int i=1;i<=2;i++)
    			for(re int j=1;j<=2;j++)
    				for(re int p=1;p<=2;p++)
    					a[i][j]=(a[i][j]+(mid[i][p]*mid[p][j])%mod)%mod;
    	}
    }R,L,K;
    inline void mul(Mat &A,Mat &B)
    {
    	LL mid[4][4];
    	for(re int i=1;i<=2;i++)
    		for(re int j=1;j<=2;j++)
    			mid[i][j]=A.ans[i][j],A.ans[i][j]=0;
    	for(re int i=1;i<=2;i++)
    		for(re int j=1;j<=2;j++)
    			for(re int p=1;p<=2;p++)
    				A.ans[i][j]=(A.ans[i][j]+(mid[i][p]*B.ans[p][j])%mod)%mod;
    	for(re int i=1;i<=2;i++)
    		for(re int j=1;j<=2;j++)
    			A.a[i][j]=A.ans[i][j];
    }
    int main()
    {
    	scanf("%s%s",N_+1,M_+1);
    	a=read(),b=read(),c=read(),d=read();
    	int lenn=strlen(N_+1);
    	if(a==1) 
    	{
    		for(re int i=1;i<=lenn;i++) n=n*10%mod+N_[i]-48;
    		n=(n-2+mod)%mod;
    	}
    	else 
    	{
    		for(re int i=1;i<=lenn;i++) n=n*10%(mod-1)+N_[i]-48;
    		n=(n-2+mod-1)%(mod-1);
    	}
    	lenn=strlen(M_+1);
    	if(c==1) 
    	{
    		for(re int i=1;i<=lenn;i++) m=m*10%mod+M_[i]-48;
    		m=(m-2+mod)%mod;
    	}
    	else 
    	{
    		for(re int i=1;i<=lenn;i++) m=m*10%(mod-1)+M_[i]-48;
    		m=(m-2+mod-1)%(mod-1);
    	}
    	R.a[1][1]=R.ans[1][1]=1;
    	R.a[2][1]=R.ans[2][1]=b;
    	R.ans[2][2]=R.a[2][2]=a;
    	R.ans[1][2]=R.a[1][2]=0;
    	K=R;
    	while(m)
    	{
    		if(m&1) R.did_ans();
    		m>>=1;
    		R.did_a();
    	}
    	L.a[1][1]=L.ans[1][1]=1;
    	L.a[2][1]=L.ans[2][1]=d;
    	L.a[2][2]=L.ans[2][2]=c;
    	L.ans[1][2]=L.a[1][2]=0;
    	mul(L,R);
    	while(n)
    	{
    		if(n&1) L.did_ans();
    		n>>=1;
    		L.did_a();
    	}
    	printf("%lld",((L.ans[2][1]+L.ans[2][2])%mod*R.ans[2][2]%mod+R.ans[2][1])%mod);
    	return 0;
    }
    
  • 相关阅读:
    Android——继续深造——从安装Android Studio 2.0开始(详)
    PHP——安装wampserver丢失MSVCR110.dll
    Marza Gift for GDC 2016
    Retrieve OpenGL Context from Qt 5.5 on OSX
    Space Time Varying Color Palette
    Screen Space Depth Varying Glow based on Heat Diffusion
    Visualization of Detail Point Set by Local Algebraic Sphere Fitting
    Glass Dragon
    Jump Flood Algorithms for Centroidal Voronoi Tessellation
    京都之行
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207869.html
Copyright © 2011-2022 走看看