[代码]SPOJ 10649 Mirror Number

Abstract

SPOJ 10649 Mirror Number

数位dp, 统计

Body

注意题目的意思是只要考虑 '0' , '1' 和 '8' 三个数字。

很普通的数位dp题……我居然还WA了2次T_T

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

int T;
char a[50], b[50];
LL f[50], g[50];

void init()
{
    int i, j;
    f[0] = 1;
    for (i = 1; i <= 45; ++i)
        if (i&1) f[i] = f[i-1]*3;
        else f[i] = f[i-1];
    g[1] = 3;
    g[2] = 2;
    for (i = 3; i <= 45; ++i)
        if (i&1) g[i] = g[i-1]*3;
        else g[i] = g[i-2]*3;
}

inline bool mirror(char c)
{return c=='0'||c=='1'||c=='8';}

bool test(int len, char *s, char c)
{
    char t[50]={0};
    for (int i = 0; i < len>>1; ++i)
    {
        if (!mirror(s[i])) return 0;
        t[i] = t[len-1-i] = s[i];
    }
    if (len&1) t[len>>1] = c;
    return strcmp(s, t)>=0;
}

bool judge(int len, char *s)
{
    for (int i = 0; i < len+1>>1; ++i)
    {
        if (!mirror(s[i])) return 0;
        if (s[i] != s[len-1-i]) return 0;
    }
    return 1;
}

LL calc(int len, char *s)
{
    int i, j, k;
    LL res = 0, tmp;
    for (i = 1; i < len; ++i)
        res += g[i];
    for (i = 0; i < len>>1; ++i)
    {
        tmp = f[len-(i+1<<1)];
        if (i && s[i]>'0') res += tmp;
        if (s[i]>'1') res += tmp;
        if (s[i]>'8') res += tmp;
        if (!mirror(s[i])) break;
    }
    if (len&1)
    {
        res += test(len, s, '0');
        res += test(len, s, '1');
        res += test(len, s, '8');
    }
    else
        res += test(len, s, 0);
    return res;
}

int main()
{
    init();
    cin>>T;
    LL ans;
    int len;
    while (T--)
    {
        /*
        scanf("%s", a);
        printf("%lld\n", calc(strlen(a), a));
        */
        scanf("%s%s", a, b);
        ans = calc(strlen(b), b)-calc(strlen(a), a);
        ans += judge(strlen(a), a);
        printf("%lld\n", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jffifa/p/SPOJ_10649.html