现在的位置: 首页 > 综合 > 正文

SPOJ MYQ10 (数位DP)

2018年10月13日 ⁄ 综合 ⁄ 共 930字 ⁄ 字号 评论关闭

思路:每位枚举1,0,8,然后对于小于了的情况可以直接计算出答案,对于等于的就搜下去,这样等于只需要在等于的一条路径上搜索,效率还是很高的

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;

const int d[3] = {0, 1, 8};

char a[50], b[50];

ll pow3[45];
int bit[45], bn;

void get(char *x) {
	bn = strlen(x);
	for (int i = 0; i < bn; i++)
		bit[i] = x[i] - '0';
}

ll dfs(int l, int r, int s, int flag) {
	if (l > r) return !flag;
	ll ans = 0;
	for (int i = s; i < 3; i++) {
		if (d[i] < bit[l])
			ans += pow3[(max(0, r - l - 1) + 1) / 2];
		else if (d[i] == bit[l]) {
			if (bit[r] < d[i]) flag = 1;
			else if (bit[r] > d[i]) flag = 0;
			ans += dfs(l + 1, r - 1, 0, flag);
		} else break;
	}
	return ans;
}

ll check() {
	int n = strlen(a);
	for (int i = 0; i <= n / 2; i++) {
		if (a[i] != '0' && a[i] != '1' && a[i] != '8') return 0;
		if (a[i] != a[n - i - 1]) return 0;
	}
	return 1;
}

ll solve(char *x) {
	get(x);
	ll ans = dfs(0, bn - 1, 1, 0);
	ans++;
	for (int i = bn - 1; i >= 1; i--)
		ans += pow3[(i + 1) / 2] / 3 * 2;
	return ans;
}

int cas;

int main() {
	pow3[0] = 1;
	for (int i = 1; i < 45; i++)
		pow3[i] = pow3[i - 1] * 3;
	scanf("%d", &cas);
	while (cas--) {
		scanf("%s%s", a, b);
		printf("%lld\n", solve(b) - solve(a) + check());
	}
	return 0;
}

抱歉!评论已关闭.