通道:http://www.spoj.com/problems/BALNUM/
题意:求【A,B】区间内奇数出现了偶数次,偶数出现奇数次的数的个数
思路:3进制压缩,0,1,2表示数字i出现了0次,1次,2次,dp[i][j][k]:前i位数位0~9出现的状态为j时的个数,这里的K代表是否包含了最高位非0,注意这里的清空要放在case外面,毕竟之前算过的状态就不要重复算了。
代码:https://github.com/Mithril0rd/Rojo/blob/master/spojbalnum.cpp
TAG:3进制压缩与数D
以下是优化后的JAVA代码,其实就是加个预处理:
dp[i][j]:前i位0~9出现了0次,奇数次,偶数次。
import java.io.*;
import java.util.*;
public class Main {
final static int MAX_D = 21;
final static int MAX_N = 59057;
int check[] = new int[MAX_N];
long dp[][] = new long[MAX_D][MAX_N];
int digit[] = new int[11], dig[] = new int[MAX_D];
int p3[] = new int[11];
int get(int x, int y) {
int t = x / p3[y];
if(t % 3 < 2) x += p3[y];
if(t % 3 == 2) x -= p3[y];
return x;
}
long dfs(int pos, int st, boolean limit) {
if (0 == pos) return dp[pos][st] = check[st];
if (!limit && -1 != dp[pos][st]) return dp[pos][st];
int end = limit ? dig[pos] : 9;
long ans = 0;
for (int i = 0; i <= end; ++i) {
boolean nxt = (st != 0) || (i != 0);
ans += dfs(pos - 1, nxt ? get(st, i) : 0, limit && i == end);
}
if (!limit) dp[pos][st] = ans;
return ans;
}
long cal(long x) {
int n = 0;
while (x > 0) {
dig[++n] = (int) (x % 10);
x /= 10;
}
return dfs(n, 0, true);
}
int F(int x) {
int id = 0;
while (x > 0) {
int num = x % 3;
if (num != 0) {
if (num == 1 && (id & 1) != 0) return 0;
else if (num == 2 && (id & 1) == 0) return 0;
}
x /= 3;
++id;
}
return 1;
}
void run() throws IOException {
for (int i = 0; i < MAX_N; ++i)
check[i] = F(i);
p3[0] = 1;
for (int i = 1; i < 11; ++i) p3[i] = p3[i - 1] * 3;
int T = cin.nextInt();
for (int i = 0; i < MAX_D; ++i)
Arrays.fill(dp[i], -1);
while (T-- > 0) {
long l = cin.nextLong();
long r = cin.nextLong();
long ans = cal(r) - cal(l - 1);
out.println(ans);
}
out.close();
}
public static void main(String[] args) throws IOException {
new Main().run();
}
Main() {
cin = new InputReader(System.in);
// cin = new Scanner(System.in);
out = new PrintWriter(System.out);
}
PrintWriter out;
InputReader cin;
//Scanner cin;
class InputReader {
InputReader(InputStream in) {
reader = new BufferedReader(new InputStreamReader(in));
// try {
// reader = new BufferedReader(new FileReader("input.txt"));
// } catch (FileNotFoundException ex) {
// }
tokenizer = new StringTokenizer("");
}
private String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public Integer nextInt() throws IOException {
return Integer.parseInt(next());
}
public Long nextLong() throws IOException {
return Long.parseLong(next());
}
private BufferedReader reader;
private StringTokenizer tokenizer;
}
}