【问题描述】
小蓝在黑板上连续写下从 1 到 2023 之间所有的整数,得到了一个数字序列:
S = 12345678910111213 . . . 20222023。
小蓝想知道 S 中有多少种子序列恰好等于 2023?
提示,以下是 3 种满足条件的子序列(用中括号标识出的数字是子序列包含的数字):
1[2]34567891[0]111[2]1[3]14151617181920212223...
1[2]34567891[0]111[2]131415161718192021222[3]...
1[2]34567891[0]111213141516171819[2]021222[3]...
注意以下是不满足条件的子序列,虽然包含了 2、0、2、3 四个数字,但是顺序不对:
1[2]345678910111[2]131415161718192[0]21222[3]...
1.dp写法
cpp
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
typedef long long LL;
typedef pair<int,int> PII;
string s;
LL dp[5];
int main()
{
IOS;
for(int i=1;i <= 2023;i++) s+=to_string(i);
for(int i=0;i < s.size();i++)
{
if(s[i] == '2')
{
dp[1]++;
dp[3]+=dp[2];
}
if(s[i] == '0') dp[2]+=dp[1];
if(s[i] == '3') dp[4]+=dp[3];
}
cout<<dp[4];
return 0;
}
2.剪枝后暴力
cpp
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
typedef long long LL;
typedef pair<int,int> PII;
string s;
LL ans=0;
string op="2023";
void dfs(int u,int cnt)
{
if(cnt == 4)
{
ans++;
return ;
}
if(u >= s.size()) return ;
if(op[cnt] == s[u]) dfs(u+1,cnt+1);
dfs(u+1,cnt);
}
int main()
{
IOS;
for(int i=1;i <= 2023;i++)
{
string t=to_string(i);
for(int j=0;j < t.size();j++)
{
if(t[j] == '2' || t[j] == '0' || t[j] == '3')
s+=t[j];
}
}
dfs(0,0);
cout<<ans<<endl;
return 0;
}
枚举四个位置,只有数字放到该放的位置,才能填下一个位置,也可以选择不填。