5379. 【NOIP2017提高A组模拟9.21】Victor爱数字 (2017.9B组)

来源:互联网 发布:php 连缀 方法 编辑:程序博客网 时间:2024/06/05 11:49

Description

Victor 是一名热爱数字的同学。他最近在思考这样一个问题:
一个字符串是回文的当且仅当它倒过来还和原来相同。那么如果一个数的数串没有一个长度超过1 的子串是回文串的话,它就是palindrome-free 的。例如:16276 是palindrome-free的,而17276 不是,因为它包含了回文串727。
Victor 想知道在a 到b 的区间内,有多少个数是palindrome-free 的。

Input

从文件numbers.in 中读入数据。
包括两个数字a,b。

Output

输出到文件numbers.out 中。
输出包含一个整数:区间a,…,b 中palindrome-free 的数的总个数(包括a,b)。

Sample Input

输入1:
123 321

输入2:
123456789 987654321

Sample Output

输出1:
153

输出2:
167386971

Data Constraint

对于16% 的数据,b - a <= 200。
对于24% 的数据,b - a <= 10^5。
对于32% 的数据,b - a <= 10^6。
对于100% 的数据,0 <= a <= b <= 10^18
想法:
数论,ans=ans(b)-ans(a-1);
如果一个数是palindrome-free的,则必有s[i]==s[i+1]||s[i]==s[i+2]
32%
如何求ans(x)?
设f[i][j][k][0/1][0/1][0/1]为构造到第i位,第i-1位为j,第i位为k,第i-1位为是否为前导0,第i位是否为前导0,前i位是否与x的前i位一样
递归求会更好
code

#include <cstdio>#include <cstring>#include <iostream>#define ll long longusing namespace std;ll f[21][11][11][2][2][2],a[19],b[19],n,m;ll gets(ll x,ll i1,ll j3,ll i2,ll j2,ll full){    if (f[x][i1][j3][i2][j2][full]>0) return f[x][i1][j3][i2][j2][full];    ll bj,bz1,bz2;    if (x==a[0])    {        f[x][i1][j3][i2][j2][full]=1;        return f[x][i1][j3][i2][j2][full];    }    ll i,sum=0;    if ((full==1)||(x==0)) bj=a[x+1];else bj=9;     for (i=0;i<=bj;i++)    {        if (((i!=j3)||(j2==0))&&((i!=i1)||(i2==0)))        {            if (((full==1)||(x==0))&&(i==a[x+1])) bz1=1;else bz1=0;            if ((j2==0)&&(i==0)) bz2=0;else bz2=1;            sum+=gets(x+1,j3,i,j2,bz2,bz1);         }       }    f[x][i1][j3][i2][j2][full]=sum;    return sum;}ll get(ll n){    memset(f,0,sizeof(f));    if (n<0) return 0;    if (n<10) return n+1;    a[0]=0;    ll t;    while (n>0)    {        a[++a[0]]=n%10;        n/=10;    }    ll i;    for (i=1;i<=a[0]/2;i++)    {        t=a[i];        a[i]=a[a[0]-i+1];        a[a[0]-i+1]=t;      }    return gets(0,0,0,0,0,0);}int main(){    freopen("numbers.in","r",stdin);    freopen("numbers.out","w",stdout);    scanf("%lld%lld",&n,&m);    ll ans=get(m);    ans-=get(n-1);    printf("%lld",ans); }