后宫

[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]

使用 dp[i][j] 代表在第 i 个指令周期中,执行第 j 条指令的妹子的数量。用转出型的
转移。
dp[i][j] 可以转移到 dp[i + 1][(j + 1) % L] ,当第 j 条指令是“ H” 时,也能转移到
dp[i + 1][0] 。观察发现 dp[i] 可以表示为 1 x L 的矩阵, dp[i] 和 dp[i + 1] 之间的转移可
以表示为边长为 L 的方阵,因此使用矩阵乘法优化即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long lol;
 7 struct Matrix
 8 {
 9   lol a[51][51];
10 }ans,Mat;
11 lol n,sum,Mod=998244353,l,anss;
12 char s[100005];
13 Matrix operator*(const Matrix x,const Matrix y)
14 {int i,j,k;
15   Matrix res;
16   memset(res.a,0,sizeof(res.a));
17   for (i=1;i<=l;i++)
18     for (j=1;j<=l;j++)
19       for (k=1;k<=l;k++)
20     res.a[i][j]+=x.a[i][k]*y.a[k][j]%Mod,res.a[i][j]%=Mod;
21   return res;
22 }
23 Matrix qpow(lol y)
24 {int i;
25   Matrix res;
26   for (i=1;i<=l;i++)
27     res.a[i][i]=1;
28   while (y)
29     {
30       if (y&1) res=res*Mat;
31       Mat=Mat*Mat;
32       y/=2;
33     }
34   return res;
35 }
36 int main()
37 {int i;
38   cin>>n;
39   cin>>s;
40   l=strlen(s);
41   for (i=0;i<l;i++)
42     if (s[i]=='H') Mat.a[i+1][1]++;
43   Mat.a[l][1]++;
44   for (i=2;i<=l;i++)
45     Mat.a[i-1][i]=1;
46   ans.a[1][1]=1;
47   Mat=qpow(n-1);
48   ans=ans*Mat;
49   for (i=1;i<=l;i++)
50     anss+=ans.a[1][i],anss%=Mod;
51   cout<<anss;
52 }

 

posted @ 2017-10-20 14:33  Z-Y-Y-S  阅读(303)  评论(0编辑  收藏  举报