SPOJ

来源:互联网 发布:淘宝店铺怎样加粉丝 编辑:程序博客网 时间:2024/05/16 09:31

1、状态压缩,用一个10位的3进制数字来表示0~9的状态,0表示未出现过,1表示出现奇数次,2表示出现偶数次。

2、输出时不要用I64d。

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <vector>#include <cstdio>#include <map>using namespace std;typedef long long int LL;LL dp[20][60000];int digit[20];// 将pre转化成3进制存放在temp中void change(int pre, int* temp){    int len = 0;    while (pre)    {        temp[len++] = pre % 3;        pre /= 3;    }}LL dfs(int pos, int pre, int lead, int limit){    if (!pos)    {        int temp[15] = {0};        change(pre, temp);        for (int i = 0; i < 10; i++)            if ((i%2==0 && temp[i]==2) || (i%2==1 && temp[i]==1))                return 0;        return 1;    }    if (!limit && dp[pos][pre] != -1)        return dp[pos][pre];    int up = limit ? digit[pos] : 9;    LL ans = 0;    for (int i = 0; i <= up; i++)    {        int temp[15] = {0};        change(pre, temp);        if (!temp[i])            temp[i] = 1;        else if (temp[i] == 1)            temp[i] = 2;        else            temp[i] = 1;        int num = 0;        for (int i = 9; i >= 0; i--)            num = num * 3 + temp[i];        ans += dfs(pos-1, (lead&&!i)?0:num, lead&&!i, limit&&i==up);    }    return limit ? ans : dp[pos][pre] = ans;}LL cal(LL n){    int len = 0;    while (n)    {        digit[++len] = n % 10;        n /= 10;    }    return dfs(len, 0, 1, 1);}int main(){    //freopen("test.txt", "r", stdin);    memset(dp, -1, sizeof(dp));    int T;    scanf("%d", &T);    while (T--)    {        LL L, R;        cin >> L >> R;        cout << cal(R) - cal(L - 1) << endl;    }    return 0;}