SPOJ 10606 Balanced Numbers 数位DP

来源:互联网 发布:淘宝二手手机可信吗 编辑:程序博客网 时间:2024/05/16 05:20

题目链接:https://vjudge.net/problem/SPOJ-BALNUM

题意:个数被称为是平衡的数当且仅当对于所有出现过的数位,偶数出现奇数次,奇数出现偶数次。

给定A,B,请统计出[A,B]内所有平衡的数的个数。

解法:

注意,这里的偶数是指出现过的数,并且不能计算前导零。

对于每一个数有三种状态:

0:这个数还木有出现过。

1:这个数出现过奇数次。

2:这个数出现过偶数次。

所以直接用一个三进制数表示状态,然后转移吧。

///SPOJ 10606#include <bits/stdc++.h>using namespace std;typedef long long LL;int dp[20][60000];int digit[20];LL pos[11];void init(){    pos[0]=1;    for(int i=1; i<=10; i++) pos[i]=pos[i-1]*3;}bool judge(int s){    for(int i=9; i>=0; i--){        if(i%2==0&&s/pos[i]==2) return false;        if(i%2==1&&s/pos[i]==1) return false;        s%=pos[i];    }    return 1;}LL dfs(int l, int s, bool zero, bool jud){    if(l==0){        if(judge(s)) return 1;        else return 0;    }    if(!jud&&dp[l][s]!=-1) return dp[l][s];    int up = jud?digit[l]:9;    LL ans=0;    for(int i=0; i<=up; i++){        ans+=dfs(l-1,zero&&i==0?0:((s%pos[i+1])/pos[i]==2?s-pos[i]:s+pos[i]), zero&&i==0, jud&&i==up);    }    if(!jud) dp[l][s] = ans;    return ans;}LL f(LL num){    int pos=0;    while(num){        digit[++pos]=num%10;        num/=10;    }    return dfs(pos,0,1,1);}int main(){    init();    memset(dp, -1, sizeof(dp));    int T;    LL a, b;    scanf("%d", &T);    while(T--){        scanf("%lld%lld", &a,&b);        printf("%lld\n", f(b)-f(a-1));    }    return 0;}
0 0
原创粉丝点击