题目链接:
求 [ l , r ] [l,r] [l,r]区间内满足以下条件数的个数:
1.任意相邻的两个数位之和为素数
2.数位中至少有一个1
3.没有前导0
本题由于l,r范围只有 1 0 10 10^{10} 1010,可以dfs暴力做,但是为了复习数位DP,下面用数位DP做。
数位DP经典先预处理f数组
- 状态表示:
f [ i ] [ j ] [ 1 ] f[i][j][1] f[i][j][1]: 满足相临数位之和为素数情况下,共有i位数,最高位为j,且数位中存在1的数的个数
f [ i ] [ j ] [ 0 ] f[i][j][0] f[i][j][0]: 满足相临数位之和为素数情况下,共有i位数,最高位为j,且数位中不存在1的数的个数 - 状态转移:
j=1时
f [ i ] [ j ] [ 1 ] + = f [ i − 1 ] [ k ] [ 0 ] + f [ i − 1 ] [ k ] [ 1 ] f[i][j][1] += f[i-1][k][0] + f[i-1][k][1] f[i][j][1]+=f[i−1][k][0]+f[i−1][k][1]
f [ i ] [ j ] [ 0 ] = 0 f[i][j][0] = 0 f[i][j][0]=0
j!=1时
f [ i ] [ j ] [ 1 ] + = f [ i − 1 ] [ k ] [ 1 ] f[i][j][1] += f[i-1][k][1] f[i][j][1]+=f[i−1][k][1]
f [ i ] [ j ] [ 0 ] + = f [ i − 1 ] [ k ] [ 0 ] f[i][j][0] += f[i-1][k][0] f[i][j][0]+=f[i−1][k][0]
注意初始化f数组时, f [ 1 ] [ 0 ] [ 0 ] f[1][0][0] f[1][0][0]要初始化为1,虽然不满足为素数,但是需要初始化为1,因为后面比如说转移到20(2位数,最高位为2,不存在1,满足相邻数位之和为素数情况)时需要用到。
然后就是转移时,需要额外标记高位是否出现过1,本题用ok标记,如果出现过,要额外进行res += f[i+1][j][0]的操作
最后要加上位数小于给定的数的情况(位数小,整体的数肯定小了)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int f[20][20][2];
bool check(int a,int b)
{
if(b < 0) return true;
if(a+b==2||a+b==3||a+b==5||a+b==7||a+b==11||a+b==13||a+b==17) return true;
return false;
}
void init()
{
f[1][0][0] = 1;
f[1][1][1] = 1;
for(int i=2;i<=9;i++) f[1][i][0] = 1;
for(int i=2;i<=10;i++)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++)
{
if(check(j,k))
{
if(j==1)
{
f[i][j][1] += f[i-1][k][0] + f[i-1][k][1];
f[i][j][0] = 0;
}
else
{
f[i][j][1] += f[i-1][k][1];
f[i][j][0] += f[i-1][k][0];
}
}
}
}
ll dp(ll x)
{
if(!x) return 0;
vector<int>nums;
while(x) nums.push_back(x%10),x/=10;
int last = -1;
ll res = 0;
bool ok = false;
for(int i=nums.size()-1;i>=0;i--)
{
int c = nums[i];
for(int j=(i==nums.size()-1);j<c;j++)
{
if(check(j,last))
{
res += f[i+1][j][1];
if(ok) res += f[i+1][j][0];
}
}
if(c==1) ok = true;
if(check(c,last)) last = c;
else break;
if(!i and ok) res ++;
}
for(int i=1;i<nums.size();i++)
for(int j=1;j<=9;j++)
res += f[i][j][1];
return res;
}
void solve()
{
init();
ll l,r;
cin>>l>>r;
cout<<dp(r)-dp(l-1)<<"\n";
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0),cout.tie(0);
int t;
// cin>>t;
t = 1;
while(t--) solve();
return 0;
}