[2019.10.25] scrimmage T3 phone number

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/ICEEBBING/article/details/102749304

cellphone number

Title Description

When people want to select the phone number easy to remember number, auspicious. Such numbers contain the same number of several adjacent, free of harmonics unlucky number and the like. Mobile phone operators when issuing new number will also consider these factors, we choose the numbers contain some features from the medium segment sold separately. In order to facilitate pre-planning, operators hope to develop a tool to automatically count the number of numbers to meet the characteristics of the segment number.
Wherein the number of tools necessary to detect two: numbers appear to be the same as at least three adjacent numbers; numbers 4 and 8 can not occur simultaneously. Characterized in comprising two numbers must satisfy a condition. Meet the conditions of numbers such as: 13000988721,23333333333,14444101000. Does not satisfy the conditions of example number: 1015400080,10010012022. Phone number must be 11 digits and does not contain leading zero. Tool receiving two numbers l and r, automatically count the number of all the numbers within the range satisfying the condition. l and r are also 11 mobile phone number.
·······························

Input Format

Only the contents of the input file line, two spaces separated by a positive integer L, R

Output Format

Output file content only one line, is an integer that represents the number of phone numbers that satisfy the condition.

analysis:

Obviously, the use of digital dp, see Notes

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXM 15
#define LL long long
#define Int register int
using namespace std;
LL num[MAXM];
LL dp[MAXM][MAXM][MAXM][2][2][2][2];
inline LL Max(LL x,LL y)
{
    return x > y ? x : y;
}
inline LL Min(LL x,LL y)
{
    return x < y ? x : y;
}
inline void read(LL &x)
{
 x = 0;
 LL f = 1;
 char s = getchar();
 while (s < '0' || s > '9')
 {
     if (s == '-')
         f = -1;
     s = getchar();
 }
 while (s >= '0' && s <= '9')
 {
     x = (x << 3) + (x << 1) + (s ^ 48);
     s = getchar();
 }
 x *= f;
}
LL Num_dp(int p,int a,int b,bool l,bool s,bool c4,bool c8)
{
 /*
 p : 当前数位
 a : p + 1位的数
 b : p + 2位的数, 如果为前导0则为 -1
 l : 判断连续
 s : 判断是否前面已经严格小于, 方便填数
 c4、c8 : 判断 4 和 8 
 */
    if (c4 && c8)
        return 0;
    if (p <= 0)
        return l;
    if (~ dp[p][a][b][l][s][c4][c8])
        return  dp[p][a][b][l][s][c4][c8];
    LL Sum = 0, Limit = ! s ? num[p] : 9;
    for (Int i = 0; i <= Limit; ++ i)
        Sum += Num_dp(p - 1, i, a, l || (i == a && a == b), s || (i < Limit), c4 || (i == 4), c8 || (i == 8));
    return dp[p][a][b][l][s][c4][c8] = Sum;
}
LL solve(LL x)
{
    if (x < 10000000000ll)
        return 0;
    memset(dp, -1, sizeof dp);
    int len = 0;
    while ( x )
    {
        num[++ len] = x % 10;
        x /= 10;
    } 
    LL Ans = 0;
    for (Int i = 1; i <= num[len]; ++ i)
        Ans += Num_dp(10, i, 0, 0, i < num[len], i == 4, i == 8);
    return Ans;
}
int main()
{
    LL L, R;
    read( L ); read( R );
    printf("%lld", solve( R ) - solve(L - 1));
    return 0;
}

Guess you like

Origin blog.csdn.net/ICEEBBING/article/details/102749304