LightOJ-1205-數位dp

題目大意:給定區間問區間內有多少數是迴文數;

題目解析:因爲給定長度,其實就已經知道看了他的對稱中心,所以從前往後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;    
}    


發佈了193 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章