The 2020 ICPC Asia Taipei-Hsinchu Site Programming Contest--C.Pyramid

Problem Description

Consider an 𝑛×𝑛 grid where nodes are labelled as (𝑖, 𝑗) for 0 ≤ 𝑖, 𝑗 < 𝑛. We rotate it 45 degree in clockwise direction and keep only its top half part. Then you get a pyramid, as shown in Figure 1. All of the nodes laid on the anti-diagonal of the grid have labels (𝑛 − 1 − 𝑗, 𝑗) for 0 ≤ 𝑗 < 𝑛. They are located at the bottom line of the pyramid. For simplicity and clarity, we name node (𝑛 − 1 − 𝑗, 𝑗) as exit 𝑗. Node (0, 0) is called the starting point (labelled as 𝑃 in Figure 1). When you insert a ball from the starting point, this ball will roll down to some of the exits. A ball located at node (𝑖, 𝑗) can only roll down to either node (𝑖 + 1, 𝑗) or node (𝑖, 𝑗 + 1), and the ball shall never be broken or split. There is a tiny switch equipped on every node other than the exits that controls the move direction of the ball, and this switch always works well. The switch has exactly two states: either 𝐿 or 𝑅, indicates that the ball can move to node (𝑖 + 1, 𝑗) or (𝑖, 𝑗 + 1), respectively. After the ball leaves this node, the switch changes immediately to the other state. The default setting for a switch is at 𝐿.

 When you insert the first ball into 𝑃, this ball will reach exit 0, and the states of nodes (𝑖, 0) for 0 ≤ 𝑖 < 𝑛 − 1 are now all 𝑅’s. Then you insert the second, third, and so on so forth, one by one, until the 𝑘 𝑡ℎ ball finishes. The status of every switch accumulates with these balls. Please write a program to determine the number of the exit point for the 𝑘 𝑡ℎ ball.

Input Format

The first line of the input is a number that specifies the number of test cases. Each test case has only one line that gives you two space-delimited numbers 𝑛 and 𝑘.

Output Format

Please output the exit number of the 𝑘 𝑡ℎ ball in one line.

Technical Specification

• There are at most 20 test cases.

• 1 ≤ 𝑛 ≤ 10^4 . • 1 ≤ 𝑘 ≤ 10^8

Input

3
5 3
5 4
5 5

Output

2
3
2

题意:刚开始每个节点都是关闭的,放球,如果该节点是关闭的,那么会向左下走,否则右下走,然后改变节点的状态(开关),问你第k个球最后落在哪个下标(从0开始)。

解析:我们可以求出前k-1的球落完之后的状态,那么模拟最后一个球就很容易了,需要知道对于一个节点,如果有m个球经过,那么有\left \lceil m/2 \right \rceil去往左边,有\left \lfloor m/2 \right \rfloor去往右边,那么我们最开始让k-1个球从起点落下跑一边就可以得到k-1的球导致的状态。

虽然可以进行优化,但是这种方法好理解😇

//Time:1715 ms   Memory:391800 KB
#include <cstdio>
const int N=10005;
int a[N][N];
void solve()
{
	int n,k;
	scanf("%d%d",&n,&k);
	a[0][0]=--k;//前k-1个球
	for(int i=0;i<n;i++)
		for(int j=0;j<=i;j++)
		{
			a[i+1][j]+=(a[i][j]+1)/2;//去往左边
			a[i+1][j+1]+=a[i][j]/2;//去往右边
		}
	int y=0;//x,y表示最后一个球所在x行y列
	for(int i=0;i<n-1;i++)//每次进入下一层
	{
		if(a[i][y]%2) y++;//如果该节点是奇数次,那么往右下走
	}
	printf("%d\n",y);
	for(int i=0;i<=n;i++)//因为多组,需要初始化
		for(int j=0;j<=i;j++) a[i][j]=0;
}
int main()
{
	int t=1;
	scanf("%d",&t);
	while(t--) solve();
	return 0;
}

优化版本

因为每一层被计算出来就可以判断最后一个小球在该层是否发生右移,这样我们其实只需要上下两层的关系,可以利用%2的滚动数组来存,然后每次计算时候记得清空再进行计算。

//Time:1216 ms    Memory:100 KB
#include <cstdio>
const int N=10005;
int a[2][N];
void solve()
{
	int n,k,y=0;
	scanf("%d%d",&n,&k);
	a[0][0]=--k;//前k-1个球
	for(int i=0;i<n-1;i++)
	{
		for(int j=0;j<=i+1;j++) a[(i+1)%2][j]=0;//滚动数组初始化
		for(int j=0;j<=i;j++)
		{
			a[(i+1)%2][j]+=(a[i%2][j]+1)/2;//去往左边
			a[(i+1)%2][j+1]+=a[i%2][j]/2;//去往右边
		}
		if(a[i%2][y]%2) y++;//直接判断在该层是否右移
	}
	printf("%d\n",y);
}
int main()
{
	int t=1;
	scanf("%d",&t);
	while(t--) solve();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值