zoukankan      html  css  js  c++  java
  • P4838 题解

    P4838 P哥破解密码题解

    思路貌似跟dalao们的有点不一样

    先前排声明一下,蒟蒻刚学OI没多久,而且是自学的,写的可能比较累赘,望见谅

    • 大致题意


    给一串长度为n的字符串,当且仅当串只由A和B构成,且没有连续的3个A时,该串合法,求方案总数


    感觉跟P4910帕秋莉的手环那道题目差不多吧....都是线性递推,貌似dalao们都是用动态规划来做的,蒟蒻不太会,所以只好用比较sb的递推来做qwq

    • 思路

    既然每个字符只有A和B两种可能,,如果字符串没有任何限制的话,很容易看出方 案总数为 : (2^n)

    但这里加了一个不能有没有连续的3个A出现的限制条件

    不妨先来画个图来看一下,更加直观一点

    图中为n=6的时候的情况

    我们用(f_i)来表示长度为i的字符串的不合法方案总数(注意,是不合法方案总数)

    先来看第一个字符选A情况

    这里我们可以把每一个B看作是一个"断点"

    不难看出,每出现一个断点后

    该断点下面的情况就可以从之前的(f_i)递推过来

    而当出现连续3个A时,相当于是把下面的所有情况都"截断"了

    也就是(2^{n-3})种情况

    第一个字符选"B"也同理

    相当于是在第一个点的时候就把该串给"截断"了

    容易推出当N=6时,合法方案总数为

    (2^6-(f_{5}+f_{4}+f_{3}+2^3))

    其他n>3的情况也同理

    得到式子

    方案总数=(2^n-(f_{n-1}+f_{n-2}+f_{n-3}+2^{n-3}))

    =(7*2^{n-3}-(f_{n-1}+f_{n-2}+f_{n-3}))

    =((2^{n-1}+2^{n-2}+2^{n-3})-(f_{n-1}+f_{n-2}+f_{n-3}))

    (s_i)为方案总数

    (s_i=s_{i-1}+s_{i-2}+s_{i-3})

    得到最终式子
    (egin{cases}2(n=1)\4 (n=2)\7 (n=3)\s_i=s_{i-1}+s_{i-2}+s_{i-3}(n>3)end{cases})

    贴个丑陋的代码

    #include<bits/stdc++.h>
    using namespace std;
    int mo=19260817;
    long long n,t;
    struct matrix{
    	long long int a[5][5];
    }ans,a;
    matrix operator *(const matrix &x,const matrix &y){
    	matrix z;
    	for(int i=1;i<=3;i++){
    		for(int j=1;j<=3;j++){
    			z.a[i][j]=0;
    		}
    	}
    	for(int k=1;k<=3;k++){
    		for(int i=1;i<=3;i++){
    			for(int j=1;j<=3;j++){
    				z.a[i][j]=(z.a[i][j]+(x.a[i][k]*y.a[k][j])%mo)%mo;
    			}
    		}
    	}
    	return z;
    }
    int main(){
    	cin>>t;
    	while(t--){
    		cin>>n;
    		if(n==1){
    			cout<<2<<endl;
    		}
    		
    	else if(n==2){
    		cout<<4<<endl;
    	}
    	else if(n==3){
    		cout<<7<<endl;
    	} 
    	else{
    		for(int i=1;i<=3;i++){
    				for(int j=1;j<=3;j++){
    					a.a[i][j]=0;
    					if(i==j) ans.a[i][j]=1;
    					else ans.a[i][j]=0;
    				}
    			}
    		a.a[1][1]=a.a[1][2]=a.a[1][3]=a.a[2][1]=a.a[3][2]=1; 
    		
    		
    		while(n){
    			if(n&1) ans=ans*a;
    			n>>=1;
    			a=a*a;
    		}
    		cout<<((ans.a[1][1]+ans.a[2][1])%mo+ans.a[3][1])%mo<<endl;
    	}
    	
    	}
    	return 0;
    }
    

    貌似是蒟蒻的第一次不看题解做出(比较水的)紫题?

  • 相关阅读:
    【Oracle】优化器之RBO与CBO
    【Oracle11g】16_数据字典和动态性能视图
    AXI总线介绍
    Verilog 加法器和减法器(8)-串行加法器
    状态机实例-寄存器拷贝
    状态机状态最小化
    vcs+Makefile实现简单的testbench
    quartus II输入原理图及仿真步骤
    Directx11代码下载
    触发器的时序参数与时序分析
  • 原文地址:https://www.cnblogs.com/xcxc82/p/13339564.html
Copyright © 2011-2022 走看看