zoukankan      html  css  js  c++  java
  • 后宫 矩阵快速幂

    [Description]
    山山是 2017 级信奥班的成员,因为良好(到大家都嫉妒的程度)的妹子缘而出名。山
    山认识的妹子实在是太多,信奥班的各位纷纷猜测山山是怎么做到的。终于,Gemin 揭开了
    这个秘密。原来,山山掌握了向妹子脑中写入程序的黑科技。山山向妹子脑中写入的程序是
    一个只含有“N”、
    “H”两种大写字母的字符串,每个大写字母代表一条指令;指令顺序执
    行,并且在执行到结尾后立即返回起始位置,依此无限循环。每条指令都耗费一个指令周期
    执行。
    两种指令的含义如下:
    “N”
    :什么都不做;
    “H”
    :执行到这条指令的妹子 A 会找到一个新的妹子 B,并在妹子 B 的大脑中写入同一段
    程序。在下一个指令周期开始时,妹子 B 会加入山山的后宫,并立即开始执行程序。
    现在,山山的后宫中只有一个妹子 Eve,在第一个指令周期开始时,Eve 会从头开始执
    行程序。现在请计算,在第 N 个指令周期结束时,山山的后宫里有多少妹子。为了避免答
    案过大,请输出答案模上 998244353 的值。
    [Input]
    第一行一个整数:N。
    下面一行,一个长度为 L 的、只含有“N”

    “H”两种大写字母的字符串 S、代表山山会
    在妹子的大脑里写入的程序。
    [Output]
    一行一个整数,代表在第 N 个指令周期结束时,山山的后宫里有多少妹子。
    [Sample]


    说明:什么都不做......


    说明:虽然在第二个周期中,Eve 找到了一个新的妹子,但是新的妹子直到第三个周期的开
    始才会加入后宫,因此第二个周期结束时仍然只有一个妹子。


    [Tips]


    我们可以把每个时刻,正在执行第几个命令的妹子数表示出来

    for(int i=1;i<=n;i++)

      for(int j=0;j<len;j++)

        if(S[j]=='N')

          f[i+1][j+1]+=f[i][j];

        if(S[j]=='H')

          {

            f[i+1][j+1]+=f[i][j];

            f[i+1][0]+=f[i][j];

          }

    我们看到整个递推式,其实很好用矩阵来表示和优化。

    首先需要快速幂的矩阵可以确定是一个行数为了len-1,列数为len-1的矩阵,因为每个时刻的每一位数量之和上个时刻的某个数有关。

    我们先可以确定矩阵最开始的雏形,由f[i+1][j+1]+=f[i][j]得出,假设了len=4:

    0 0 1

    1 0 0

    0 1 0

    而每次碰到H,只有第0行会加上f[i][j],所以我们只用在第0行加上1就可以了。

    假如当前字符串是:

    NH

    那我们可以构造出矩阵:

    0 2

    1 0

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    
    #define ll long long
    #define il inline
    #define db double
    
    #define mod 998244353
    
    using namespace std;
    
    char S[145],len;
    
    struct mul
    {
    	ll a[145][145];
    	mul ()
    	{
    		memset(a,0,sizeof(a));
    	}
    }hehe;
    
    il mul chen(mul x,mul y)
    {
    	mul p;
    	for(int i=0;i<len;i++)
    		for(int j=0;j<len;j++)
    			for(int k=0;k<len;k++)
    				p.a[i][j]=(p.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
    
    	return p;
    }
    
    il mul pow(mul x,int b)
    {
    	mul tmp;
    	for(int i=0;i<len;i++)
    		for(int j=0;j<len;j++)
    			tmp.a[i][j]=0;
    	tmp.a[0][0]=1;
    	while(b)
    		{
    			if(b&1)
    				tmp=chen(x,tmp);
    			x=chen(x,x);
    			b>>=1;
    		}
    	return tmp;
    }
    
    int main()
    {
    	freopen("harem.in","r",stdin);
    	freopen("harem.out","w",stdout);
    
    	int n;
    	cin>>n;
    	
    	cin>>S;
    	
    	len=strlen(S);
    
    	mul T;
    	T.a[0][len-1]=1;
    	for(int i=1;i<len;i++)
    		T.a[i][i-1]=1;
    
    	for(int i=0;i<len;i++)
    		if(S[i]=='H')
    			T.a[0][i]++;
    
    	mul ans=pow(T,n-1);
    
    	int sum=0;
    	for(int i=0;i<len;i++)					 
    		sum=(sum+ans.a[i][0])%mod;
    
    	printf("%d
    ",sum);
    		
    	return 0;
    }
    
  • 相关阅读:
    BizTalk2010简介
    各大类库的类工厂
    全国城市三级级联菜单(java+Ajax+jQuery)
    gcc编译系统
    通用排行榜组件
    本地化中文示例代码需求调查
    PortalBasic Java Web 应用开发框架(源码、示例及文档)
    FFLIB 框架
    ORM/IOC框架设计感悟
    个人日记
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7700183.html
Copyright © 2011-2022 走看看