1. 程式人生 > 其它 >【數位DP】luogu_P7415 Count the Cows G

【數位DP】luogu_P7415 Count the Cows G

數位DP

題意

對於每一個滿足\(x≥0\)以及\(y≥0\)的方格\((x,y)\),當對於所有整數\(k≥0\)\(\left\lfloor \frac{x}{3^k}\right\rfloor\)\(\left\lfloor \frac{y}{3^k}\right\rfloor\)除以三的餘數的奇偶性均相同時,有一頭奶牛位於\((x,y)\)
換言之,兩個餘數均為奇數(均等於\(1\)),或均為偶數(均等於\(0\)\(2\))。

例如,滿足\(0≤x,y<9\)的方格中,包含奶牛的方格在下圖中用 1 表示。

        x
    012345678

  0 101000101
  1 010000010
  2 101000101
  3 000101000
y 4 000010000
  5 000101000
  6 101000101
  7 010000010
  8 101000101

他進行了 QQ 個詢問,每個詢問由三個整數\(x_i,y_i,d_i\)組成。
對每個詢問,FJ想要知道有多少奶牛位於\((x_i,y_i)\)\((x_i+d_i,y_i+d_i)\)的對角線上的方格內(包括兩端)。

思路

先對一個\(k\)進行分析。
\(x=3^ka+r_0\)
\(y=3^kb+r_1\)
​因為研究\(a\)\(b\)的關係,再提一個\(3\)
\(x=3^k(3p_x+q_x)+r_0\)
\(y=3^k(3p_y+q_y)+r_1\)
展開即為:
\(x=3^{k+1}p_x+3^kq_x+r_0\)
\(y=3^{k+1}p_y+3^kq_y+r_1\)
對於\(r_0\)

,\(r_1\),我們也可以將它們分成包含若干\(3\)的次冪的式子。
最後變成三進位制的形式。
\(x = \sum_{k = 0} 3^k a_{k}\)
\(y = \sum_{k = 0} 3^k b_{k}\)
在上面分析過,單獨對於每個k來看,\(a_k\)\(b_{k}\)\(\% 2\)同餘。

故滿足條件的\((x,y)\)\(x、y\)在三進位制情況下的每位\(\% 2\)同餘。

用數位dp計算即可。

程式碼

#include <cstdio>
#include <cstring>

const int n = 38;
int q;
int X[39], Y[39], D[39], v[39][2][2][2];
long long f[39][2][2][2];

int check(int a, int b) {
	if (a < 0 || a > 2 || b < 0 || b > 2)
		return 0;
	return (a & 1) == (b & 1);
}

long long dp(int dep, int a, int b, int flag) {//當前數位,是否向dep+1進位,,d有沒有頂到
	if (dep < 0)
		return !a && !b;
	if (v[dep][a][b][flag])
		return f[dep][a][b][flag];
	v[dep][a][b][flag] = 1;
	long long res = 0;
	for (int i = 0; i <= (flag ? D[dep] : 2); i++)//flag的體現
		for (int j = 0; j <= 1; j++)//列舉下一位要不要向當前位進位
			for (int k = 0; k <= 1; k++)
				if (check(X[dep] - 3 * a + i + j, Y[dep] - 3 * b + i + k))
					res += dp(dep - 1, j, k, flag & (D[dep] == i));
	return f[dep][a][b][flag] = res;
}

int main() {
	scanf("%d", &q);
	long long d, x, y;
	while (q--) {
		memset(v, 0, sizeof(v));
		scanf("%lld %lld %lld", &d, &x, &y);
		for (int i = 0; i <= n; i++) {
			X[i] = x % 3;
			x /= 3;
			Y[i] = y % 3;
			y /= 3;
			D[i] = d % 3;
			d /= 3;
		}
		printf("%lld\n", dp(n, 0, 0, 1));
	}
}