LightOJ-1205-数位dp

12 篇文章 0 订阅

题目大意:给定区间问区间内有多少数是回文数;

题目解析:因为给定长度,其实就已经知道看了他的对称中心,所以从前往后dfs,判断前i位的时候,要判断后面是否可以取到,如果不可以去到,那么后面那位的前一位就必须小于limit,所以dfs要多一个变量ok;

AC代码:

#include<iostream>    
#include<cstdio>    
#include<cstring>    
#include<string>    
#include<algorithm>    
using namespace std;    
typedef long long ll;    
ll dp[50][50];    
int num[50];    
ll dfs(int pos,int l,bool ok,bool limit)    
{    
	int r=pos-l+1;
    if(r>l)	return	ok||(!limit);
    if(!limit&&dp[pos][l]!=-1) return dp[pos][l];    
    int u=limit?num[l]:9;    
    ll ans=0;    
    for(int i=(l==pos)?1:0;i<=u;i++)    
    {    
		if(ok&&num[r]>=i)	ans+=dfs(pos,l-1,true,limit&&i==u);
		else if(!ok&&num[r]>i)	ans+=dfs(pos,l-1,true,limit&&i==u);   
		else ans+=dfs(pos,l-1,false,limit&&i==u);
    }    
    if(!limit)   return dp[pos][l]=ans;    
    return ans;    
}    
ll solve(ll n)    
{    
	if(n==0)	return 1;
	if(n<0)	return 0;
    int cnt=0;    
    while(n)    
    {    
        num[++cnt]=n%10;    
        n/=10;    
    } 
	ll ans=1;   
    for(int i=cnt;i>=1;i--)
	 	ans+=dfs(i,i,true,i==cnt);
	return ans;
}    
int main()    
{    
    ll a,b;    
    memset(dp,-1,sizeof(dp));   
    int cas,c=1;  
    scanf("%d",&cas);   
    while(cas--)    
    {    
        scanf("%lld%lld",&a,&b);  
        if(a>b)
        {
        	ll t=a;
        	a=b;
        	b=t;
        }
        printf("Case %d: ",c++);  
        printf("%lld\n",solve(b)-solve(a-1));               
    }    
    return 0;    
}    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值