arc117_c - Tricolor Pyramid(卢卡斯定理,贪心,思维)

本文解析AtCoder竞赛中一道关于颜色金字塔构建的问题。通过计算每个底层方块对顶层方块颜色的影响,利用卢卡斯定理高效解决大规模数据输入的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://atcoder.jp/contests/arc117/tasks/arc117_c

Problem Statement

We have NN blocks arranged in a row, where each block is painted blue, white, or red. The color of the ii-th block from the left (1≤i≤N) is represented by a character ci; BW, and R stand for blue, white, and red, respectively.

From this situation, we will pile up blue, white, and red blocks to make a pyramid with N steps. The following figure shows an example of this:

 

Here, we place blocks one by one from bottom to top as follows:

  • if the two blocks immediately below a position have the same color, we will place there a block of the same color;
  • if the two blocks immediately below a position have different colors, we will place there a block of the color different from those two colors.

What will be the color of the block at the top?

Constraints

  • NN is an integer satisfying 2≤N≤400000
  • Each of c1,c2,…,cN is BW, or R.

Input

Input is given from Standard Input in the following format:

N
c1c2⋯⋯cN

Output

If the topmost block will be blue, print B; if it will be white, print W; if it will be red, print R.

一道很好的思维题目,对于最后一行,我们可以算每一个格子对最后答案的“贡献”。令b=0,w=1,r=2 。对于最后一行第一个格子,他的贡献次数为1次,第二个格子贡献次数为C(n-1,1)次,C()为组合数。以此类推(相当于从最上面一行开始走到当前格子有几种走法)。

所以最后把最后一行每个格子的权重乘以次数再对3取模就i可以了。

由于n比较大,我们可以用卢卡斯定理处理。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>
using namespace std;
long long F[10010];
long long mod = 3;
void init(long long p)
{
	F[0] = 1;
	for (int i = 1; i <= p; i++)
		F[i] = F[i - 1] * i % (mod);
}
long long inv(long long a, long long m)
{
	if (a == 1)return 1;
	return inv(m%a, m)*(m - m / a) % m;
}
long long Lucas(long long n, long long m, long long p)
{
	long long ans = 1;
	while (n&&m)
	{
		long long a = n % p;
		long long b = m % p;
		if (a < b)return 0;
		ans = ans * F[a] % p*inv(F[b] * F[a - b] % p, p) % p;
		n /= p;
		m /= p;
	}
	return ans;
}
int main()
{
	int n;
	scanf("%d", &n);//b,w,r=0,1,2
	init(3);
	char ch[400005];
	map<char, int>M;
	for (int i = 0; i < n; i++)
	{
		cin >> ch[i];
	}
	M['B'] = 0;
	M['W'] = 1;
	M['R'] = 2;
	int ans=0;
	int sign;
	if (n % 2 == 0)
		sign = -1;
	else
		sign = 1;
	for (int i = 0; i < n; i++)
	{
		int t = Lucas(n - 1, i,3)*M[ch[i]];
		t = t * sign;
		if (t < 0)
		{
			int tem = (-t) / 3 + 1;
			t = t + 3 * tem;
		}
		ans += t;
		ans = ans % 3;
	}
	if (ans == 0)
		puts("B");
	else if (ans == 1)
		puts("W");
	else
		puts("R");
	//system("pause");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值