USACO 2020~2021 February Contest GOLD 题解(3)

USACO 2020~2021 二月黄金组 题解(3)

3. Count The Cows

As is typical, Farmer John’s cows have spread themselves out along his largest pasture, which can be regarded as a large 2D grid of square “cells” (picture a huge chessboard).
The pattern of cows across the pasture is quite fascinating. For every cell (x,y) with x≥0 and y≥0, there exists a cow at (x,y) if for all integers k≥0, the remainders when ⌊x3k⌋ and ⌊y3k⌋ are divided by three have the same parity. In other words, both of these remainders are odd (equal to 1), or both of them are even (equal to 0 or 2).
FJ is curious how many cows are present in certain regions of his pasture. He asks Q queries, each consisting of three integers xi,yi,di. For each query, FJ wants to know how many cows lie in the cells along the diagonal range from (xi,yi) to (xi+di,yi+di) (endpoints inclusive).

题目大意:农夫John的牛在一个二维方阵里吃草。对于方阵中的某个格子(x,y)(x,y为自然数),该方格中有牛当且仅当对于所有非负整数k,都有 ⌊ x / 3 k ⌋ \lfloor x/3^k \rfloor x/3k ⌊ y / 3 k ⌋ \lfloor y/3^k \rfloor y/3k除以3的余数同奇偶。现在John一共会作出Q次询问(1 ≤ \leq Q ≤ \leq 104 ),每个询问包含三个整数x,y,d(0 ≤ \leq x,y,d ≤ \leq 1018),询问在以(x,y)上顶点,(x+d,y+d)为下顶点的对角线上牛的总头数。

思路分析: 这道题乍一看是一道描述不算简单的数论题,我们先打一下表(其实通过题目中给出的样例也可以看出一些规律):

101000101
010000010
101000101
000101000
000010000
000101000
101000101
010000010
101000101

我们有如下猜想:整个方格是一个形状为“X”的分形图。下面提供对这一猜想的粗略证明:考虑背靠原点3*3个边长为3k的方格,将每个分割为9个边长为3k-1的小方格。可以发现,每个大方格的横纵坐标在除以3取余数之后,都会被映射至左上方大方格内的相对位置一致的小方格:如果大方格横纵坐标除以三之余数奇偶性不同,那么这个大方格不满足条件,因此对应小方格也不满足条件。运用数学归纳法的思想,可以推出对于任意的正整数k,在背靠原点的3 * 3个边长为3k的方格,横纵坐标奇偶性不同的方格没有牛,而横纵坐标奇偶性相同的方格与左上方小方格构图相同。因此,整个方格是一个形状为“X”的分形图。

有了这个重要的观察,我们可以运用递归的思想,将边长为3k的正方形对角线在O(1)的时间内转化为对边长为3k-1的正方形对角线的求解。具体来说,定义f(k,dif)为在以原点为起点,边长为3^k的正方形中所有满足x−y=dif且有牛的方格(x,y)的个数(也就是该正方形左下角边长为dif的正方形的对角线上有牛的方格的个数)。那么:
f ( k , d i f ) = { 3 f ( k − 1 , d i f ) dif <  3 k − 1 f ( k − 1 , d i f − 2 ( 3 k − 1 ) ) dif ≥   3 k − 1 f(k,dif)= \begin{cases} 3f(k-1,dif)&\text{dif < $3^{k-1}$}\\ f(k-1,dif-2 (3^{k-1}))&\text{dif$\geq$ $3^{k-1}$} \end{cases} f(k,dif)={3f(k1,dif)f(k1,dif2(3k1))dif < 3k1dif 3k1
回答每个询问时,可以用边长为(x+d)的答案减去边长为(x-1)的答案。算法复杂度为O(Qlog(max(x+d)))。具体解析详见代码。

官方解法代码如下:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
 
vector<LL> po3 = [](){
	vector<LL> res{1};
	for (int i = 1; i < 40; ++i) 
		res.push_back(3*res.back());
	return res;
}();//将3的k次幂先预处理,方便使用

LL full[40];
void gen_full(int k, ll dif) //预处理x-y=dif的正方形的函数
{ 
	dif = abs(dif);//dif为负时横纵颠倒,不影响
	if (k == 0) 
	{
		full[k] = (dif == 0);//边界处理:横纵坐标相等时显然有牛
		return;
	}
	if (dif >= po3[k-1])
	{
		gen_full(k-1,dif-2*po3[k-1]);
		full[k] = full[k-1];
	} 
	else
	{
		gen_full(k-1,dif);
		full[k] = 3*full[k-1];
	}//代入转移方程
}
 
ll rec(ll x, ll y, int k) {
	x %= po3[k], y %= po3[k];//求余数
	if (k == 0) return 1;//处理边界情况
	if (x < y) swap(x,y);
	//考虑“X”的形状,9个位置分类讨论
	if (x-y >= po3[k-1]) {
		if (x < 2*po3[k-1]) return 0;
		if (y < po3[k-1]) return rec(x,y,k-1);
		if (y >= po3[k-1]) return full[k-1];
	}
	if (x < po3[k-1]) return rec(x,y,k-1);
	if (y < po3[k-1]) return full[k-1];
	if (x < 2*po3[k-1]) return full[k-1]+rec(x,y,k-1);
	if (y < 2*po3[k-1]) return 2*full[k-1];
	return 2*full[k-1]+rec(x,y,k-1);
}
LL diag(ll x, ll y) {
	if (x < 0 || y < 0) return 0;
	gen_full(39,x-y);//预处理dif=x-y的最大正方形
	return rec(x,y,39);
}
int Q; 
int main() {
	scanf("%d",&Q);
	while(Q--)
	{
		LL d,x,y;
		scanf("%lld%lld%lld",&d,&x,&y);
		printf("%lld",diag(x+d,y+d)-diag(x-1,y-1));//差分思想
	}
}

本次比赛其他题目:

USACO 2020~2021 二月黄金组 题解(1)Stone Game
USACO 2020~2021 二月黄金组 题解(2)Modern Art 3

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
USACO2022金组是国际在线判题系统USACO的最高级别,题目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些题目解析。 第一题:“交通计划” 题目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该题可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二题:“点火计划” 题目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该题可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三题:“美味佳肴” 题目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该题可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分题目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值