梦境中的迷宫 Solution

题目定位:欺诈题

题目难度:普及/提高–

注意到题目里得分的构造方式,我们可以发现只要答案给错了得分一定比较少,因此我们必须每次给出正确的答案。
然后,我们观察得分的形式:由于 2 n 2^n 2n的乘数因子是固定的,因此我们可以把它提出来,问题等价于只要求方案数即可。由一些组合数最基本的定义得到第 i i i个路口的答案一定是 C n i C^i_n Cni。最终答案应该是 ∑ i = 0 n C n i \sum\limits_{i=0}^{n}C^i_n i=0nCni。然后把它摆在杨辉三角形里相当于求杨辉三角形整行的和,因此我们由组合恒等式 ∑ i = 0 n C n i = 2 n \sum\limits_{i=0}^{n}C^i_n=2^{n} i=0nCni=2n即可将问题转化为求 2 2 n % 998244353 = 4 n % 998244353 2^{2n}\%998244353=4^{n}\%998244353 22n%998244353=4n%998244353的结果。
注意到 998244353 998244353 998244353是个质数,我们由费马小定理知道 4 998244352 % 998244353 = 1 4^{998244352}\%998244353=1 4998244352%998244353=1,所以我们只需要将 n n n 998244353 998244353 998244353取模然后快速幂计算结果即可。

然而考虑到这个 n n n实在是太大了,所以我们必须要采用如下的方式来解决:
输入文件总计 10 M B 10MB 10MB左右,换算之: 10 ∗ 1024 ∗ 1024 ≈ 1 0 7 10*1024*1024\approx10^7 1010241024107,大约是 1 0 7 10^7 107个数字。我们有如下的解决方案:

1.对于 C + + C++ C++选手你可以考虑在快速读入时做这样的改变。
这是原本的快速读入:

#define Fermat 998244352
#define mod 998244353
inline int read()
{
	int n=0,k=1;
	char c=getchar();
	while(c>'9'||c<'0') c=getchar();
	while(c>='0'&&c<='9') n=(n<<1)+(n<<3)+(c^48),c=getchar();
	return n;
}

如果我们加费马小定理优先取模,可以这么做:

#define Fermat 998244352
#define mod 998244353
inline int read()
{
	int n=0,k=1;
	char c=getchar();
	while(c>'9'||c<'0') c=getchar();
	while(c>='0'&&c<='9') n=(n<<1)+(n<<3)+(c^48),n%=Fermat,c=getchar();
	return n;
}

主程序中调用

int n=read();

这样可以直接得到对 998244352 998244352 998244352取模过后的 n n n
当然你想直接字符串读进来写个高精对单精取模也是可以的。

2.对于Pascal选手,你没有可以这么做的快速读入,但你仍然可以这么做

while not eof do
begin
	read(c);
	n:=n*10+odd(c)-48;
	n:=n mod 998244352;
end;

(我没有卡语言,我很良心)

3.对于Python,Java等语言的选手:你们可以使用BigInt,当然只要你不怕TLE

另外,如果你们注意到Pascal,Python和Java(如果有)等语言的程序始终因为TLE而无法通过,你可以将运行时间限制调整到 2 s 2s 2s

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值