题目
解题思路:不考虑最后一种|S|>2的情况
动态规划
下一秒的字符串依赖于上一秒的字符串。以|S|=1为例,依赖关系如下表所示
上一秒的数字 | 下一秒的数字 |
---|---|
1 | 2 |
2 | 4 |
4 | 1和6 |
6 | 6和4 |
知道上一秒1246四个数字的个数,便可推的下一秒四个数字各自的个数。
考虑|S|=2的情况,考虑到11、12等字符不会出现在最终的结果中,最终的结果中只会出现1、2、4、6、16、26、41、42、44、46、61、62、64、66这14种情况,除此之外便可直接输出0。
上一秒出现的4、41、42、44、46、64等情况均会导致下秒出现16,但他们均是因为含有4才会出现16,为避免重复,下一秒16的个数仅依赖与上秒中4的个数。类似的情况还有下一秒64的个数仅依赖于上秒中6和42的个数。
从而得到|S|<=2时的依赖情况如下表所示
1 | 2 | 4 | 6 | 16 | 26 | 41 | 42 | 44 | 46 | 61 | 62 | 64 | 66 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
16 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
26 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
41 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
42 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
44 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
46 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
61 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
62 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
64 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
66 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
表中最左边一列代表上秒的数字,最上面一行代表下一秒的数字,为1时存在依赖关系,为0时不存在依赖关系。
算法加速满足时间要求
参考斐波那契数列数列的求法,构造dp矩阵如下:
long long int dp[14][14]={
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}
};
初始时2的个数为1,构造初始矩阵如下:
long long int begin_matrix[14]={0,1,0,0,0,0,0,0,0,0,0,0,0,0};
最终的结果:result=begin_matrix*dp^(n-1)
采用分治算法求解矩阵的n次方,参考我的博客幂乘算法
代码
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define RAW 14
#define COL 14//定义数组大小
using namespace std;
long long int begin_matrix[14]={0,1,0,0,0,0,0,0,0,0,0,0,0,0};
long long int result[14]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
long long int dp_n[14][14];
void mul_matrix(long long a[RAW][COL],long long b[RAW][COL],long long c[RAW][COL]){
for(int i=0;i<RAW;++i){
for(int k=0;k<COL;++k){
c[i][k]=0;
for(int j=0;j<COL;++j){
c[i][k]+=a[i][j]*b[j][k];
if(c[i][k]>=998244353) c[i][k]=c[i][k]%998244353;
}
}
}
}
void final_result(){
for(int k=0;k<14;++k){
for(int j=0;j<14;++j){
result[k]+=begin_matrix[j]*dp_n[j][k];
}
}
}
void copy_matrix(long long a[][COL],long long b[][COL]){
for(int i=0;i<RAW;++i)
for(int j=0;j<COL;++j)
b[i][j]=a[i][j];
}
void matrix_n(long long a[][COL],long long c[][COL],long long int n){
if(n==2){
mul_matrix(a,a,c);
return;
}
if(n==1){
copy_matrix(a,c);
return;
}
if(n%2==0){
matrix_n(a,c,n/2);
long long copy_c[RAW][COL];
copy_matrix(c,copy_c);
mul_matrix(copy_c,copy_c,c);
return ;
}
else{
matrix_n(a,c,(n-1)/2);
long long copy_c[RAW][COL];
copy_matrix(c,copy_c);
mul_matrix(copy_c,copy_c,c);
copy_matrix(c,copy_c);
mul_matrix(copy_c,a,c);
}
}
int main(){
long long int dp[14][14]={
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}
};
long long int n;
cin>>n;
if(n>1){
matrix_n(dp,dp_n,n-1);
final_result();
}
else{
result[1]=1;
}
int output;
cin>>output;
switch(output){
case 1:
cout<<result[0];
break;
case 2:
cout<<result[1];
break;
case 4:
cout<<result[2];
break;
case 6:
cout<<result[3];
break;
case 16:
cout<<result[4];
break;
case 26:
cout<<result[5];
break;
case 41:
cout<<result[6];
break;
case 42:
cout<<result[7];
break;
case 44:
cout<<result[8];
break;
case 46:
cout<<result[9];
break;
case 61:
cout<<result[10];
break;
case 62:
cout<<result[11];
break;
case 64:
cout<<result[12];
break;
case 66:
cout<<result[13];
break;
default:
cout<<0;
break;
}
return 0;
}
得分
不考虑最后一种情况,理应得到96分,但提交后只有92分,实在找不出问题在哪,欢迎大家在评论区指出我的错误