数位DP JZOJ 3316. 非回文数字

题目

Description
如果一个字符串从后往前读与从前往后读一致,我们则称之为回文字符串。当一个数字不包含长度大于1的子回文数字时称为非回文数字。例如,16276是非回文数字,但17276不是,因为它包含回文数字727。

你的任务是在一个给定的范围内计算非回文数字的总数。
 
Input
输入仅一行,包含两个整数a和b。
Output
输出仅一行,包含一个整数,表示a到b范围内(包括a和b)非回文数字的总数。
 
Sample Input
输入1:
123 321
输入2:
123456789 987654321
Sample Output
输出1:
153
输出2:
167386971
 
Data Constraint
25%的数据:b-a<=100 000.

100%的数据:0<=a<=b<=10^18

 

分析

 

  • 第一道数位DP
  • 模板直接套

 

代码

 

 

 1 #include<iostream>
 2 #include<cstring>
 3 #define ll long long
 4 using namespace std;
 5 ll a[100],pos;
 6 ll f[20][10][10][2][2][2]; 
 7 ll dfs(ll pos,ll pre2,ll pre1,bool zero2,bool zero1,bool lim) //zero为标记前导零是否存在 
 8 {
 9     if (f[pos][pre2][pre1][zero1][zero2][lim]!=-1) 
10       return f[pos][pre2][pre1][zero1][zero2][lim];  //记忆化搜索 
11     ll ans=0;
12     if (pos<1) return 1;
13     ll end=lim?a[pos]:9;
14     for (ll i=0;i<=end;i++)
15     {
16         if ((zero2||i!=pre2)&&(zero1||i!=pre1))   //因为存在0就无法成为串 
17           ans+=dfs(pos-1,pre1,i,zero1,zero1&&(i==0),lim&&i==end);
18     }
19     if (f[pos][pre2][pre1][zero1][zero2][lim]==-1) f[pos][pre2][pre1][zero1][zero2][lim]=ans;
20     return ans;
21 }
22 ll calc(ll x)
23 {
24     pos=0;
25     memset(f,-1,sizeof(f));
26     while (x) a[++pos]=x%10,x/=10;
27     return dfs(pos,0,0,1,1,1);
28 }
29 int main ()
30 {
31     ll l,r;
32     cin>>l>>r;
33     cout<<calc(r)-calc(l-1);
34 }

 

数位Dp模板

 1 ll dfs(int cut,bool limit,bool sta)
 2 {
 3     if(cut==0) return 1;
 4     ll ans=0;
 5     int cu=limit?a[cut]:9;
 6     for(int i=0;i<=cu;i++)
 7     {
 8         if(i==2 && sta) continue;
 9         if(i!=4)
10         ans+=(dfs(cut-1, limit & (i==a[cut]) ,i==6));
11     }
12     return ans;
13 }
14  
15 ll solve(ll x)
16 {
17     int cut=0;
18     while(x){
19         a[++cut]=(x%10);
20         x/=10;
21     }
22     return dfs(cut,1,0);
23 }
24  
25 int main()
26 {
27     ll a,b;
28     while(1)
29     {
30         cin>>a>>b;
31         if(a==0 && b==0) return 0;
32         cout<<solve(b)-solve(a-1)<<endl;
33     }
34      
35     return 0;
36 }

 

转载于:https://www.cnblogs.com/zjzjzj/p/11135057.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值