Balanced Numbers SPOJ - BALNUM (数位dp)
题目链接:https://cn.vjudge.net/contest/163023#problem/J
题目大意:
问A到B之间有多少个数,有多少数 符合以下两个条件。
数位0-9 中 ,每一个奇数数位有 偶数个, 偶数数位有奇数个。也就是如果有1 的话,那必须有偶数个1。如果有2的话,必须有奇数个2,当然没有也可以。
题目分析:问A到B之间有多少个数,有多少数 符合以下两个条件。
数位0-9 中 ,每一个奇数数位有 偶数个, 偶数数位有奇数个。
也就是如果有1 的话,那必须有偶数个1。如果有2的话,必须有奇数个2,当然没有也可以。注意前导零是不能算的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[30][60000];
int data[30];
bool judge(int s)
{
for(int i = 0; i <= 9; i++) //依次去判断每一位
{
if((s % 3 == 1) && (i & 1)) return false;
if((s % 3 == 2) && !(i & 1)) return false;
s /= 3;
}
return true;
}
int cal(int now, int x)
{
int num = x, tmp = now;
while(num--)//找到x对应的那一位
{
tmp /= 3;
}
tmp %= 3; //计算有多少个x
if(tmp == 0 || tmp == 1) now += (int)pow(3.0, x); //当前位变为奇数
else now -= (int)pow(3.0, x); //当前位变为偶数数
return now;
}
ll dfs(int pos, int s, bool limit)
{
if(pos == -1) return judge(s);
if(!limit && dp[pos][s] != -1) return dp[pos][s];
int up = limit ? data[pos] : 9;
ll ans = 0;
for(int i = 0; i <= up; i++)
{
ans += dfs(pos - 1, (s == 0 && i == 0) ? 0 : cal(s, i), i == data[pos] && limit);
}
if(!limit) dp[pos][s] = ans;
return ans;
}
ll solve(ll n)
{
int pos = 0;
while(n)
{
data[pos++] = n % 10;
n /= 10;
}
return dfs(pos - 1, 0, true);
}
int main()
{
int t;
memset(dp, -1, sizeof(dp));
scanf("%d", &t);
while(t--)
{
ll a, b;
scanf("%lld %lld", &a, &b);
printf("%lld\n", solve(b) - solve(a - 1));
}
return 0;
}