【luogu P7415】Count the Cows G(数位DP)(数学)

Count the Cows G

题目链接:luogu P7415

题目大意

有一个矩阵。
如果 x,y 这两个数,对于每个 k,它们除 3^k 的余数的奇偶性都相同,那 x,y 这个位置是 1,否则就是 0。
然后要你统计 x,y 到 x+d,y+d 这条对角线上有多少个 1。

思路

首先我们观察这个是否有 1 1 1
那它每次都是 3 k 3^k 3k,其实就是要看它三进制的每一位是否都奇偶性对应相同。

然后你就考虑数位 DP。
大概也是从高位向低位搞,然后也是看是否跑满,然后还要看一个就是是否进位(因为你是两个数都加一个数,就加了可能会某一位进位),然后 DP 一下即可。

代码

#include<cstdio>
#include<cstring>
#define ll long long

using namespace std;

int q, dd[51], xx[51], yy[51];
ll d, x, y, ans, rem[51][2][2][2];

bool ck(int x, int y) {
	if (x < 0 || x > 2) return 0;
	if (y < 0 || y > 2) return 0;
	return (x & 1) == (y & 1);
}

ll dfs(int x, int a, int b, bool lim) {//数位 DP(x 是当前位数,ab 是两个的进位,lim 是是否选满)
	if (!x) return (!a && !b);
	if (rem[x][a][b][lim] != -1) return rem[x][a][b][lim];
	ll re = 0;
	
	for (int i = 0; i <= (lim ? dd[x] : 2); i++) {
		for (int aa = 0; aa <= 1; aa++)
			for (int bb = 0; bb <= 1; bb++) {
				if (ck(xx[x] - 3 * a + aa + i, yy[x] - 3 * b + bb + i))
					re += dfs(x - 1, aa, bb, lim & (i == dd[x]));
			}
	}
	
	return rem[x][a][b][lim] = re;
}

int main() {
	scanf("%d", &q);
	
	while (q--) {
		scanf("%lld %lld %lld", &d, &x, &y);
		
		memset(dd, 0, sizeof(dd));
		memset(xx, 0, sizeof(xx));
		memset(yy, 0, sizeof(yy));
		while (d) {
			dd[++dd[0]] = d % 3;
			d /= 3;
		}
		while (x) {
			xx[++xx[0]] = x % 3;
			x /= 3;
		}
		while (y) {
			yy[++yy[0]] = y % 3;
			y /= 3;
		}
		

		memset(rem, -1, sizeof(rem));
		printf("%lld\n", dfs(50, 0, 0, 1));
	}
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值