题目链接: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;
}