SPOJ

题意:

  求出所给范围内满足其数位上的奇数出现偶数次,数位上的偶数出现奇数次(或不出现)的数的个数。

思路:

  对于0 ~ 9 每个数有3种情况。

  1.没出现过 2.出现奇数次 3.出现偶数次

  那么就可以用三进制来表示状态。

#include <iostream>
#include <cstring> 
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 60000;
int t;
int bits[25];
ll l, r;
ll dp[25][N];
ll judge(ll x) {
    for(int i = 0; i <= 9; i++, x/=3) 
    if(x%3 == (i+1)%2+1) return 0;
    return 1;
}
ll change(ll x, int pos) {
    int j = pos;
    ll res = x;
    while(j--) res /= 3;
    res = res%3;
    if(res < 2) x += (int)pow(3, pos);
    else x -= (int)pow(3, pos);
    return x;
}
ll dfs(int pos, int state, bool limit) {
    if(pos < 0) return judge(state);
    if((!limit) && (~dp[pos][state])) return dp[pos][state];
    int up = limit?bits[pos]:9;
    ll res = 0;
    for(int i = 0; i <= up; i++)
    res += dfs(pos-1, state==0&&i==0?0:change(state, i), limit && i==up);
    if(!limit) dp[pos][state] = res;
    return res;
}
ll solve(ll x) {
    int pos = 0;
    while(x) {
        bits[pos++] = x%10;
        x /= 10;
    }
    return dfs(pos-1, 0, 1);
}
int main() {
    memset(dp, -1, sizeof(dp));
    scanf("%d", &t);
    while(t--) {
        scanf("%lld%lld", &l, &r);
        printf("%lld
", solve(r) - solve(l-1));
    }
}
View Code
原文地址:https://www.cnblogs.com/Pneuis/p/8120061.html