str[i] = str[i - 3] + str[i - 1].substr(str[i - 4].size()) + str[i - 2];
这样出现的限制主要在空间方面,内存不够储存数字串
#include
#include
using namespace std;
int main()
{
int n;
string s_num;
cin >> n >> s_num;
string str[1010];
str[1]="2";
str[2]="4";
str[3]="16";
str[4]="264";
int ans=0, position=0;
//生成数字串
for(int i=5;i<=n;i++)
str[i]=str[i-3]+str[i-1].substr(str[i-4].size())+str[i-2];
string str_n = str[n];
while ((position = str_n.find(s_num, position)) != string::npos)
{
position++;
ans++;
if(ans>998244353)
ans%=998244353;
}
cout<<ans;
return 0;
}
第一种暴力方法差强人意,我们换个角度
注意到有24个测试点竟然只是 ∣ S ∣ = 1 |S|=1 ∣S∣=1或 ∣ S ∣ = 2 |S|=2 ∣S∣=2。
1.考虑一位,只有1,2,4,6四种情况,
2.考虑两位,根据前10个数字串发现,无非 16 , 26 , 41 , 44 , 46 , 61 , 62 , 64 , 66 , 42 16,26,41,44,46,61,62,64,66,42 16,26,41,44,46,61,62,64,66,42这10种
依次给14个数编号
d p [ ] [ 1 ] = 1 , d p [ ] [ 1 ] = 2 , d p [ ] [ 3 ] = 4 , d p [ ] [ 4 ] = 6 , d p [ ] [ 5 ] = 16 , d p [ ] [ 6 ] = 26 , d p [ ] [ 7 ] = 41 dp[][1]=1,dp[][1]=2 ,dp[][3]=4 ,dp[][4]=6, dp[][5]=16,dp[][6]=26 ,dp[][7]=41 dp[][1]=1,dp[][1]=2,dp[][3]=4,dp[][4]=6,dp[][5]=16,dp[][6]=26,dp[][7]=41……
那我们可以根据线性递推的DP公式写出变换矩阵(根据线性递推的DP公式如何写出变换矩阵)
#include
#define ll long long
using namespace std;
const int mod = 998244353;
//矩阵快速幂模板
struct mat
{
ll m[15][15];
}unit,a;
void init()
{
for(int i=1;i<15;i++)
unit.m[i][i]=1;
}
mat matmul(mat a,mat b)//c=矩阵a*矩阵b
{
mat c;
ll tmp =0;
for(int i=1;i<15;i++)
for(int j=1;j<15;j++)
{
tmp=0;
for(int k=1;k<15;k++)
{
tmp=(tmp+a.m[i][k]*b.m[k][j])%mod;
}
c.m[i][j]=tmp;
}
return c;
}
mat QuickPow(mat a,ll n)//ans=矩阵a^n
{
for(int i=1;i<15;i++)
unit.m[i][i]=1;
mat ans=unit;
while(n)
{
if(n&1)
ans=matmul(ans,a);
a = matmul(a,a);
n>>=1;
}
return ans;
}
//对S=1和S=2写入编号
map<string,int>mp;
void init_1()
{
mp["1"] = 1; mp["2"] = 2; mp["4"] = 3; mp["6"] = 4;
mp["16"] = 5; mp["26"] = 6; mp["41"] = 7; mp["44"] = 8;
mp["46"] = 9; mp["61"] = 10; mp["62"] = 11; mp["64"] = 12;
mp["66"] = 13; mp["42"] = 14;
};
int main()
{
mat a=
{
{
{
0,0,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}, //1
{
0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}, //2
{
0,0,1,0,1,0,0,0,0,0,0,0,0,0,0}, //3
{
0,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, //4
{
0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, //5
{
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0}, //6
{
0,0,0,0,0,0,0,0,0,0,0,0,1,0,0}, //7
{
0,0,0,0,0,0,0,0,0,0,0,1,0,0,0}, //8
{
0,0,0,0,0,0,1,0,0,0,0,0,0,1,0}, //9
{
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0}, //10
{
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0}, //11
{
0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, //12
{
0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}, //13
{
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0} //14
}};
init_1();
int n;
cin>>n;
mat ans=QuickPow(a,n);
string s;
cin>>s;
int t = mp[s];
ll answer = 0;
answer = (ans.m[t][1])%mod;
cout<<answer<<endl;
}