数位DP记搜写法10pts求助
查看原帖
数位DP记搜写法10pts求助
588201
hh20080501hh楼主2024/9/12 17:18

正常思路,具体见注释

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1010 , mod = 1e9+7;

int dp[N][15][15];
int num[N];
string L , R;

int dfs (int pos , bool limit , bool lead , int lst1 , int lst2 , bool ok)//pos为当前位置,limit为是否被高位限制,lead表示是否有前导0,lst1、lst2分别代表更高位上的两个数 
{
	if (!pos) return ok;
	if (dp[pos][lst1][lst2]!=-1 && lead && !limit) return dp[pos][lst1][lst2];
	int res = 0 , high = 9;
	if (limit) high = num[pos];
	for (int i=0 ; i<=high ; i++)
	{
		res += dfs(pos-1 , limit&&(i==high) , i||lead , (i||lead)?i:10 , lst1 , lead&&(ok||(i==lst1)||(i==lst2)));
		res %= mod;
	}
	if (!limit && lead) dp[pos][lst1][lst2] = res;
	return res;
}

inline int work (string s)
{
	int len = 0;
	for (int i=s.size()-1 ; i>=0 ; i--)
	{
		num[++len] = s[i]-'0';
	}
	return dfs(len , 1 , 0 , 10 , 10 , 0)%mod;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	
	cin >> L >> R;
	for (int i=L.size()-1 ; i>=0 ; i--)
	{
		if (L[i]!='0')
		{
			L[i] -= 1;
			break;
		}
		else 
		{
			L[i] = '9';
		}
	}
	memset(dp , -1 , sizeof dp);
	cout << ((work(R)-work(L)%mod)+mod)%mod << '\n';
	return 0;
}
2024/9/12 17:18
加载中...