分手了不太开心QAQ,写篇博客吧。这题是区间dp的问题,题意就是给你无限个1145141919,有t次询问,询问的n小于等于5000,问是否存在这样的前缀使得你操作无限次加、乘和括号,没啥思路,看了大佬的代码,发现是有规律的?我这种菜鸡来打表都不会,那当且仅当前缀长度小于等于13,那就区间dp好了,dp[l][r][val] 代表l到r之间val这个值是不是合法,预处理的时候记得粘连在一起的部分也要算,例如“1145”,那么dp[1][4][1145]=true。
贴上代码OVO:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
#include<sstream>
#define x first
#define y second
#define lson u<<1
#define rson u<<1|1
#define pb push_back
#define pu pushup
#define mk make_pair
using namespace std;
#define ll long long
#define mod 1000000007
inline int read(){
   
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){
   if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
bool dp[20][20][5010];
int num[20]={
   0,1,1,4,5,1,4,1,9,1,9,1,1,4,5,1};
int main()
{
   
	int t;
	cin>>t;
	for(int i=1;i<=13;i++)
	   {
   
	   	int temp=0;
	   	for(int j=i;j<=13;j++)
	   {
   
	   		temp=(temp*10+num[j]);
	   		if(temp>=1 && temp<=5000)
	   		dp[i][j][temp]=true;
	   }
		}
	for(int i=2;i<=13;i++)
		for(int j=1;j+i-1<=13;j++)
		{
   
			int r=j+i-1;
			for(int k=j;k<=r-1;k++)
				{
   
				for(int v1=1;v1<=5000;v1++)
					{
   
						if(!dp[j][k][v1])	continue;
					for(int v2=1;v2<=5000;v2++)
						{
   
							if(!dp[k+1][r][v2])	continue;
							if(v1+v2<=5000)
							dp[j][r][v1+v2]|=dp[j][k][v1]&dp[k+1][r][v2];
							if(v1*v2<=5000)
							dp[j][r][v1*v2]|=dp[j][k][v1]&dp[k+1][r][v2];
						}
					}
				}
		}
	for(int i=1;i<=5000;i++)
	{
   
		bool flag=false;
		for(int j=1;j<=13;j++)
		{
   
			if(dp[1][j][i])	
			flag=true;
		}
		if(!flag)	cout<<i<<endl;	
	}
	while(t--)
	{
   
		int n;
		cin>>n;
		bool flag=false;
		for(int i=1;i<=13;i++)
			if(dp[1][i][n])
				{
   
					cout<<i<<endl;
					flag=true;
					break;
				}
		if(!flag)
		puts("-1");		
	}
}