天天看點

【數位DP】SPOJ BALNUM Balanced Numbers

通道: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;
	}
}
           

  

轉載于:https://www.cnblogs.com/Rojo/p/4066504.html