演算法隨筆——數位DP

codwarm發表於2024-06-01

學習連結 https://www.luogu.com/article/tzeo544s

數位DP標準模版:

ll dfs(int pos,int pre,int st,……,int lead,int limit)//記搜
{
	if(pos>len) return st;//剪枝
	if((dp[pos][pre][st]……[……]!=-1&&(!limit)&&(!lead))) return dp[pos][pre][st]……[……];//記錄當前值
	ll ret=0;//暫時記錄當前方案數
	int res=limit?a[len-pos+1]:9;//res當前位能取到的最大值
	for(int i=0;i<=res;i++)
	{
        //有前導0並且當前位也是前導0
		if((!i)&&lead) ret+=dfs(……,……,……,i==res&&limit);
        //有前導0但當前位不是前導0,當前位就是最高位
		else if(i&&lead) ret+=dfs(……,……,……,i==res&&limit); 
		else if(根據題意而定的判斷) ret+=dfs(……,……,……,i==res&&limit);
	}
	if(!limit&&!lead) dp[pos][pre][st]……[……]=ret;//當前狀態方案數記錄
	return ret;
}
ll part(ll x)//把數按位拆分
{
	len=0;
	while(x) a[++len]=x%10,x/=10;
	memset(dp,-1,sizeof dp);//初始化-1(因為有可能某些情況下的方案數是0)
	return dfs(……,……,……,……);//進入記搜
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld%lld",&l,&r);
	    if(l) printf("%lld",part(r)-part(l-1));//[l,r](l!=0)
	    else printf("%lld",part(r)-part(l));//從0開始要特判
	}
	return 0;
}

相關文章