ACdream群OJ-完美数-简单数位dp

完美数

Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 128000/64000 KB (Java/Others)
Problem Description
8是中国人很喜欢的一个数字,但是如果有3的存在就变成了38。。。就不是很好了。。 你能告诉我,在[L , R] 的正整数区间内,要么包含3 要么包含 8 的不同的整数有多少个么?
Input
第一行一个整数T(<=10000),代表数据的组数。 对于每组数据给两个整数 L , R (1 <= L <= R <= 1e9)。
Output
对于每组数据,给一个整数为答案。
Sample Input
3
1 100
1 3
8 8
Sample Output
34
1
1
Source
/****************************
* author:crazy_石头
* date:2014/04/25
* time: 8 ms 
* algorithm:数位dp+二分 
* Pro:XMU 1519
***************************/
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             using namespace std; #define INF INT_MAX #define eps 1e-8 #define A system("pause") #define rep(i,h,n) for(int i=(h);i<=(n);i++) #define ms(a,b) memset((a),(b),sizeof(a)) #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define LL long long const int maxn=250+5; const int maxm=30; LL dp[maxn][maxn],digit[maxn],l,r,s; //=0表示不含3和8 1表示含3 2表示含8 4表示3 8同时出现 inline LL dfs(LL pos,LL status,LL limit) { if(pos==-1) return status==1||status==2; if(!limit&&~dp[pos][status]) return dp[pos][status]; LL ret=0,end=limit?digit[pos]:9; for(int i=0;i<=end;i++) { int new_num=status; if(status==0&&i!=3&&i!=8) new_num=0; if(status==0&&i==3&&i!=8) new_num=1; if(status==0&&i!=3&&i==8) new_num=2; if(status==1&&i!=3&&i==8) new_num=4; if(status==1&&i==3&&i!=8) new_num=1; if(status==1&&i!=3&&i!=8) new_num=1; if(status==2&&i==3&&i!=8) new_num=4; if(status==2&&i!=3&&i!=8) new_num=2; if(status==2&&i!=3&&i==8) new_num=2; if(status==4) new_num=4; //if(status==1) new_num=1; //if(status==2) new_num=2; ret+=dfs(pos-1,new_num,limit&&i==end); } if(!limit) return dp[pos][status]=ret; return ret; } inline LL solve(LL n) { LL len=0; while(n) { digit[len++]=n%10; n/=10; } return dfs(len-1,0,1);//limit等于1表示后继状态未搜完,等于0表示后继状态已经搜完了;答案放进dp数组就行; } int main() { int test; scanf("%d",&test); while(test--) { ms(dp,-1); scanf("%lld%lld",&l,&r); printf("%lld\n",solve(r)-solve(l-1)); } return 0; } 
            
           
          
         
       
      
      
     
     
    
    
   
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值