数位DP
数位DP
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=20;
int a,b,s[N],ten[N],dp[N][N][2][2];
/*
记录状态为
走到第p位,目前答案是多少
还有多少约束条件就再开多少维 
是否达到上界(limit),是否有前导0(lead) 
的情况下往后走可以得到多少这个数
*/
int dfs(int p,其他约束条件,int sum,int limit,int lead)
{
	if(!p) return sum;也有可能不是返回sum,在下面的例题里有这种情况 
	if(dp[p][sum][limit][lead]!=-1) return dp[p][sum][limit][lead];
	
	int up=limit?上限:s[p],ans=0;
	
	for(int i=0;i<=up;++i)
	ans+=dfs(p-1,其他约束条件,sum+(i==d&&(d||lead)),limit||i<up,i||lead,d);
	
	return dp[p][sum][limit][lead]=ans;
}
inline int work(int x,int d)
{
	memset(dp,-1,sizeof(dp));
	s[0]=0;
	while(x) s[++s[0]]=x%10,x/=10;
	return dfs(s[0],0,0,0,d);
}
signed main()
{
	输入和求值 
}
P2657[SCOI2009] windy数


#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n,a[N],dp[N][N];
void init()
{
	for(int i=0;i<=9;++i) dp[1][i]=1;
	
	for(int i=2;i<=10;++i)
	for(int j=0;j<=9;++j)
	for(int k=0;k<=9;++k)
	if(abs(j-k)>=2) dp[i][j]+=dp[i-1][k];
}
int query(int x)
{
	a[0]=0;
	while(x) a[++a[0]]=x%10,x/=10;
	
	int res=0;
	for(int i=1;i<a[0];++i)
	for(int j=1;j<=9;++j)
	res+=dp[i][j];
//	cout<<res<<" "; 
	for(int i=1;i<a[a[0]];++i)
	res+=dp[a[0]][i];
	
//	cout<<res<<" ";
	for(int i=a[0]-1;i;--i)
	{
		for(int j=0;j<a[i];++j)
		if(abs(j-a[i+1])>=2) res+=dp[i][j];
		
		if(abs(a[i+1]-a[i])<2) break;
	}
	
//	cout<<res<<"\n";
	return res;
}
int main()
{
	init();
	int x,y;
	cin>>x>>y;
	cout<<query(y+1)-query(x);
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=20;
int a,b,s[N],ten[N],dp[N][N][2][2];
/*
记录状态为
走到第p位,当前所求数字有sum个,
是否达到上界(limit),是否有前导0(lead) 
的情况下往后走可以得到多少这个数 
*/
int dfs(int p,int sum,int limit,int lead,int d)
{
	if(!p) return sum;
	if(dp[p][sum][limit][lead]!=-1) return dp[p][sum][limit][lead];
	
	int up=limit?9:s[p],ans=0;
	
	for(int i=0;i<=up;++i)
	ans+=dfs(p-1,sum+(i==d&&(d||lead)),limit||i<up,i||lead,d);
	
	return dp[p][sum][limit][lead]=ans;
}
inline int work(int x,int d)
{
	memset(dp,-1,sizeof(dp));
	s[0]=0;
	while(x) s[++s[0]]=x%10,x/=10;
	return dfs(s[0],0,0,0,d);
}
signed main()
{
	cin>>a>>b;
	for(int i=0;i<=9;++i) 
	cout<<work(b,i)-work(a-1,i)<<" ";
}
P4999 烦人的数学作业
双 倍 经 验
本题相当于求\([L,R]\)之间每个数字出现的次数\(cnt\),然后\(ans+=i*cnt[i]\)就可以得到最终答案。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=20;
int a,b,ans,mod=1e9+7,s[N],ten[N],dp[N][N][2][2];
int dfs(int p,int sum,int limit,int lead,int d)
{
	if(!p) return sum;
	if(dp[p][sum][limit][lead]!=-1) return dp[p][sum][limit][lead];
	
	int up=limit?9:s[p],ans=0;
	
	for(int i=0;i<=up;++i)
	ans=(ans+dfs(p-1,sum+(i==d&&(d||lead)),limit||i<up,i||lead,d))%mod;
	
	return dp[p][sum][limit][lead]=ans;
}
inline int work(int x,int d)
{
	memset(dp,-1,sizeof(dp));
	s[0]=0;
	while(x) s[++s[0]]=x%10,x/=10;
	return dfs(s[0],0,0,0,d);
}
signed main()
{
	int T;scanf("%lld",&T);
	while(T--)
	{
		int ans=0;
		scanf("%lld %lld",&a,&b);
		for(int i=0;i<=9;++i) ans=(ans+i*(work(b,i)-work(a-1,i)+mod)%mod)%mod;
		printf("%lld\n",ans);
	}
}
P1836 数页码
三 倍 经 验
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=20;
int a,b,ans,s[N],ten[N],dp[N][N][2][2];
/*
记录状态为
走到第p位,当前所求数字有sum个,
是否达到上界(limit),是否有前导0(lead) 
的情况下往后走可以得到多少这个数 
*/
int dfs(int p,int sum,int limit,int lead,int d)
{
	if(!p) return sum;
	if(dp[p][sum][limit][lead]!=-1) return dp[p][sum][limit][lead];
	
	int up=limit?9:s[p],ans=0;
	
	for(int i=0;i<=up;++i)
	ans=ans+dfs(p-1,sum+(i==d&&(d||lead)),limit||i<up,i||lead,d);
	
	return dp[p][sum][limit][lead]=ans;
}
inline int work(int x,int d)
{
	memset(dp,-1,sizeof(dp));
	s[0]=0;
	while(x) s[++s[0]]=x%10,x/=10;
	return dfs(s[0],0,0,0,d);
}
signed main()
{
	
	int ans=0;
	scanf("%lld",&a);
	for(int i=0;i<=9;++i) ans=ans+i*work(a,i);
	printf("%lld\n",ans);
	
}
P6218 [USACO06NOV] Round Numbers S
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=40;
int a,b,ans,s[N],ten[N],dp[N][N][N][2][2];
int tt;
/*
记录状态为
走到第p位,0有x0个,1有x1个
(只有不存在前导0的情况下才会对0计数) 
是否达到上界(limit),是否有前导0(lead) 
的情况下往后走可以得到多少这个数 
*/
int dfs(int p,int x0,int x1,int limit,int lead)
{
	if(!p) return x0>=x1;
	if(dp[p][x0][x1][limit][lead]!=-1) return dp[p][x0][x1][limit][lead];
	
	int up=limit?1:s[p],res=0;
	for(int i=0;i<=up;++i) 
	if(i==0) res+=dfs(p-1,x0+lead,x1,limit||i<up,lead||i);
	else res+=dfs(p-1,x0,x1+1,limit||i<up,lead||i);
	return dp[p][x0][x1][limit][lead]=res;
}
inline int work(int x)
{
	memset(dp,-1,sizeof(dp));
	s[0]=0;
	while(x) s[++s[0]]=x&1,x>>=1;
	tt=(s[0]+1)/2;
	return dfs(s[0],0,0,0,0);
}
signed main()
{
	scanf("%lld %lld",&a,&b);
	printf("%lld\n",work(b)-work(a-1));
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号