• 51Nod 1668 非010串


    这是昨天上课ChesterKing dalao讲线代时的例题

    当时看到这道题就觉得很水,记录一下后面两位的情况然后讨论一下转移即可

    由于之前刚好在做矩阵题,所以常规的矩阵快速幂优化也很简单

    好我们开始看题目

    首先很容易考虑到所有的情况只和最后两位有关,所以我们设a,b,c,d表示结尾为10,11,01,00的方案数,然后每一次增加位数,都有新的a',b',c'd'这转移为:

    • a'=a

    • b'=b+c

    • c'=a+d

    • d'=a+d

    然后这个就是尿性的矩阵优化了,我们可以稍加分析得出递推矩阵:

    1 0 0 0
    0 1 1 0
    1 0 0 1
    1 0 0 1

    然后矩阵快速幂求之即可

    CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int N=5,mod=1e9+7;
    LL n;
    struct Matrix
    {
    	int n,m;
    	LL a[N][N];
    	inline void Dt_init(void)
    	{
    		n=m=4; memset(a,0,sizeof(a));
    		a[1][2]=a[2][2]=a[2][3]=a[3][1]=a[3][4]=a[4][1]=a[4][4]=1;
    	}
    	inline void cri_init(void)
    	{
    		n=m=4; memset(a,0,sizeof(a));
    		a[1][1]=a[2][2]=a[3][3]=a[4][4]=1;
    	}
    	inline LL get_sum(void)
    	{
    		LL ans=0;
    		for (register int i=1;i<=n;++i)
    		for (register int j=1;j<=m;++j)
    		ans=(ans+a[i][j])%mod;
    		return ans;
    	}
    };
    inline Matrix mul(Matrix A,Matrix B)
    {
    	Matrix C; C.n=A.n; C.m=B.m; memset(C.a,0,sizeof(C.a));
    	for (register int i=1;i<=C.n;++i)
    	for (register int j=1;j<=C.m;++j)
    	for (register int k=1;k<=A.m;++k)
    	C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
    	return C;
    }
    inline Matrix quick_pow(Matrix A,LL p)
    {
    	Matrix T; T.cri_init();
    	while (p)
    	{
    		if (p%2) T=mul(T,A);
    		A=mul(A,A); p/=2;
    	}
    	return T;
    }
    int main()
    {
    	scanf("%lld",&n); Matrix A; A.Dt_init();
    	if (n==1) { puts("2"); return 0; }
    	if (n==2) { puts("4"); return 0; }
    	A=quick_pow(A,n-2);
    	printf("%lld",A.get_sum());
    	return 0;
    }
    
  • 相关阅读:
    Redis主从复制
    Redis发布订阅
    Redis持久化
    初探redis.config
    java连接Linux服务器问题
    Redis常见类型及API
    Redis安装
    Nosql
    JMM
    SpringSecurity
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9088042.html
Copyright © 2020-2023  润新知