一个数称为平衡数, 满足他各个数位里面的数, 奇数出现偶数次, 偶数出现奇数次, 求一个范围内的平衡数个数。
用三进制压缩, 一个数没有出现用0表示, 出现奇数次用1表示, 出现偶数次用2表示, 这样只需要开一个20*60000的数组。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6 #define lson l, m, rt<<1 7 #define mem(a) memset(a, 0, sizeof(a)) 8 #define rson m+1, r, rt<<1|1 9 #define mem1(a) memset(a, -1, sizeof(a)) 10 #define mem2(a) memset(a, 0x3f, sizeof(a)) 11 #define rep(i, a, n) for(int i = a; i<n; i++) 12 #define ull unsigned long long 13 typedef pair<int, int> pll; 14 const double PI = acos(-1.0); 15 const double eps = 1e-8; 16 const int mod = 1e9+7; 17 const int inf = 1061109567; 18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 19 int digit[20], a[20]; 20 ll dp[20][60000]; 21 int judge(int num) { 22 int cnt = 0; 23 for(int i = 0; i<10; i++) { 24 a[i] = num%3; 25 num/=3; 26 } 27 for(int i = 0; i<10; i++) { 28 if(i%2==0&&a[i]==2) 29 return 0; 30 if(i%2==1&&a[i]==1) 31 return 0; 32 } 33 return 1; 34 } 35 int cal(int num, int tmp) { 36 int cnt = 0; 37 for(int i = 0; i<10; i++) { 38 a[i] = num%3; 39 num/=3; 40 } 41 a[tmp]++; 42 if(a[tmp]==3) 43 a[tmp]=1; 44 for(int i = 9; i>=0; i--) { 45 num = num*3+a[i]; 46 } 47 return num; 48 } 49 ll dfs(int len, int num, int fp, bool first) { 50 if(!len) { 51 return judge(num); 52 } 53 if(!fp&&dp[len][num]!=-1) { 54 return dp[len][num]; 55 } 56 ll ret = 0; 57 int maxx = fp?digit[len]:9; 58 for (int i = 0; i<=maxx; i++) { 59 ret += dfs(len-1, (first&&i==0)?0:cal(num, i), fp&&i==maxx, i==0&&first); 60 } 61 if(!fp) 62 return dp[len][num] = ret; 63 return ret; 64 } 65 ll cal(ll n) { 66 int len = 0; 67 while(n) { 68 digit[++len] = n%10; 69 n/=10; 70 } 71 return dfs(len, 0, 1, true); 72 } 73 int main() 74 { 75 mem1(dp); 76 int t; 77 ll a, b; 78 cin>>t; 79 while(t--) { 80 scanf("%lld%lld", &a, &b); //I64d会超时...... 81 printf("%lld\n", cal(b)-cal(a-1)); 82 } 83 }
时间: 2024-11-20 02:46:22