对于这道题,我们设一位数有三个状态,
0:该位是前导零
1::该位是奇数
2:该位是偶数
最终仿照状压dp将状态压缩进dp数组二维。
dp[i][k] 前i位数字,状态为k的个数。
下面是ac代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1e5+5;
typedef unsigned long long ull;
ll f[30][60000];
int su[60];
int che(int sta)
{
for (int i = 0; i <= 9; i++)
{
if ((i&1) && sta % 3 == 1)
return 0;
if (!(i&1) && sta%3 == 2)
return 0;
sta /= 3;
}
return 1;
}
int change(int sta, int i)
{
int te = sta;
int j = i;
while(j--)
{
te /= 3;
}
int x = te % 3;
if (x==0)
sta += (int)pow(3.0, i);
else if (x == 1)
sta += (int)pow(3.0, i);
else sta -= (int)pow(3.0, i);
return sta;
}
ll dp(int cur, int sta, bool flag)
{
if (!cur) return che(sta);
if (!flag &&f[cur][sta] != -1) return f[cur][sta];
ll ans = 0;
int mx = flag?su[cur]:9;
for (int i = 0; i <= mx; i++)
ans += dp(cur-1, sta==0&&i==0?0:change(sta, i), flag&&i==mx);
if (!flag) return f[cur][sta] = ans;
return ans;
}
ll so(ll a)
{
int len = 0;
while(a)
{
su[++len] = a%10;
a /= 10;
}
return dp(len, 0, 1);
}
int main()
{
int t;
cin >>t;
memset(f, -1, sizeof(f));
while(t--)
{
ll l, r;
cin >> l >> r;
cout << so(r) - so(l-1) << endl;
}
}