类型:数位DP
题意:定义平衡数为:以某位数为中心,左边的每位数*这个数离中心的距离 == 右边的每位数*这个数离中心的距离。问[x,y]之间有多少平衡数
思路:
做的莫名奇妙……
定义:dp[i][d][k][b] 为 首位为d的i位数,以第k位为中心点,平衡因子为b的数的个数。平衡因子定义为,中心点右边的和-中心点左边的和。
实际上这个状态定义冗余了。不需要定义首位d,同时,平衡因子如果定义成,之前所有数的加权和为b,那就不有写这么复杂了。
唉,现在有点乱。理不清楚啊。
#include <cstdio> #include <cstring> #include <iostream> #define BB 1000 using namespace std; long long dp[20][10][20][BB+BB]; int num[30]; long long dfs(int i, int d, int k, int b, bool isQuery) { #ifdef _D printf("(%d,%d,%d,%d,%d) ", i, d, k, b, isQuery); #endif if (k < 0) return 0; if (k >= BB+BB) return 0; long long &nowdp = dp[i][d][k][b]; if (!isQuery && dp[i][d][k][b] != -1) { #ifdef _D printf("(%d,%d,%d,%d,%d) ", i, d, k, b, isQuery); printf("return %d ", ((i-k)*d+BB == b)); #endif return dp[i][d][k][b]; } if (i == 1) { #ifdef _D printf("(%d,%d,%d,%d,%d) ", i, d, k, b, isQuery); printf("return %d ", ((i-k)*d+BB == b)); #endif return nowdp = ((i-k)*d+BB == b); } long long ans = 0; int nextB = b-(i-k)*d; int end = isQuery?num[i-1]:9; for (int j = 0; j <= end; j++) { ans += dfs(i-1, j, k, nextB, isQuery && j==end); } if (!isQuery) nowdp = ans; #ifdef _D printf("(%d,%d,%d,%d,%d) ", i, d, k, b, isQuery); printf("return %d ", ans); #endif return ans; } long long cal(long long x) { if (x == -1) return 0; int len = 0; if (x == 0) { num[++len] = 0; } else { while (x) { num[++len] = x%10; x /= 10; } } long long ans = 0; for (int i = 1; i <= len; i++) { ans += dfs(len+1, 0, i, BB, true); } ans -= len-1; // 每种平衡点,都会算一次0这个数 return ans; } int Nmain() { long long x; memset(dp, -1, sizeof(dp)); //while (cin>>x) { long long pre = -1; for (int i = 0; i < 9999999; i++) { x = i; if (cal(x) > pre+1) { cout<<x<<endl; pre = cal(x); getchar(); } pre = cal(x); } return 0; } int main() { int t; scanf("%d", &t); memset(dp, -1, sizeof(dp)); while (t--) { long long x, y; cin>>x>>y; cout<<cal(y)-cal(x-1)<<endl; } return 0; }