GMOJ 7237. 【USACO 2021 February Contest, Gold】Problem 3 Count the Cows题解

GMOJ 7237. 【USACO 2021 February Contest, Gold】Problem 3 Count the Cows题解

题目自己看。

Solution

打个表
容易发现这个01矩阵有一定规律
假设初始矩阵为 X X X
每次把它代入
( X 0 X 0 X 0 X 0 X ) \left( \begin{array}{l} X & 0 & X\\ 0 & X & 0\\ X & 0 & X \end{array} \right) X0X0X0X0X
这样就好做了.
首先把询问转化成两个前缀和相减的形式,然后由对称性强制x>y,那么问题转化为求助阵中从 ( 0 , x ) (0,x) (0,x)开始连续对角线 r r r个的前缀和.

考虑最简单也是最基本的形式,最后一个点的横纵坐标的最大值为 3 3 3的幂次.
那么这个点一定在一个形如
( X 0 X 0 X 0 X 0 X ) \left( \begin{array}{l} X & 0 & X\\ 0 & X & 0\\ X & 0 & X \end{array} \right) X0X0X0X0X的矩阵中
讨论一下
( 0 , x ) (0,x) (0,x)可以在三个位置,分别递归去算就行了.
这样,我们解决了最基本的问题.

考虑如何推广
对于任意的 ( 0 , x ) (0,x) (0,x)最后一个点的横纵坐标最大值不一定落在 X X X的边界.
很自然地可以想到构造 x = ∑ i 3 i p i x=\sum_i3^ip_i x=i3ipi然后继续讨论 ( 0 , x ) (0,x) (0,x)去做即可.
需要注意一些细节.

Code(考场)

#include <cstdio>
#include <iostream>
#define LL long long
using namespace std;
LL x, Q, y, d, p[50];
inline LL read() {
	LL res = 0; char ch = getchar();
	while(!isdigit(ch)) ch = getchar();
	while(isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return res;
}
LL g(int x, LL y) {
	if(y & 1) return 0;
	if(x == 0 && y == 0) return 1;
	LL tmp = p[x - 1] << 1;
	if(y < p[x - 1]) return 3 * g(x - 1, y);
	else if(y < tmp) return g(x - 1, tmp - y);
	else return g(x - 1, y - tmp);
}
LL f(LL x, LL r) {
	if(r <= 0) return 0;
	LL res = 0, s;
	for(int i = 39; i >= 0; --i) {
		s = x + r;
		if(s >= p[i]) {
			if(s / p[i] == 1) {
				if(x >= p[i]) break;
				res += g(i, x);
				r -= p[i], ++i;	
			}
			else if(s / p[i] == 2) {
				LL tmp = p[i] << 1;
				if(x < p[i]) 
					res += (g(i, x) << 1),
					r -= tmp, ++i;
				else if(x >= p[i] && x < tmp) 
					x = tmp - x,
					r = min(p[i] - x, r - x), ++i;
				else if (x >= tmp) 
					x -= tmp, ++i;
			}
			if(r <= 0) break;
		}
	}
	return res;
}
int main() {
	Q = read();
	p[0] = 1;
	for(int i = 1; i <= 39; ++i)
		p[i] = p[i - 1] * 3;
	while(Q--) {
		d = read(), x = read(), y = read();
		if(y > x) swap(x, y);
		printf("%lld\n",f(x - y, d + y + 1) - f(x - y, y));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值