hdu 6822 Paperfolding 规律+排列组合+逆元
2024-10-21 13:34:45
题意:
给你一片纸,你可以对它进行四种操作,分别是向上、向下、向左、向右对折。把对折之后的纸片横向剪开,再纵向剪开(十字架剪开)
问你你能剪出来的纸片的期望个数
题解(参考:https://blog.csdn.net/fztsilly/article/details/107799718):
很显然,向下和向上对折是一样的,向左和向右对折一样。那么也就变成了两种对折方式(这里为向下和向右)。选择其中某种方法可能性为1/2,同时对折的先后顺序不影响最后结果,即“右右下”和“下右右”对折后剪开的纸片数量一样
规律:往上下方向折k次,会有2k条割线,那么横着切一刀展开后的纸片数有2k+1张,这个+1就是最中间折痕左右两边纸片算一个,同理左右折。
假设折n次的情况下,设左右折次数为k,那么上下折次数为n−k。
那么总纸片数量为:(2k+1)*(2n-k+1)
因为折纸片的折叠操作顺序可以改变(“右右下”和“右下右”折出来的纸片数量都一样),所以这个结果应该乘于Ckn ,又因为最后结果是期望,且一种操作执行概率为1/2,那么最后再乘于1/2n
代码:
#include<stack>
#include<queue>
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn=6e6+1;
const int mod=998244353;
const ll inv2 = 499122177;
ll quick_pow(ll a, ll b)
{
ll ans = 1, base = a;
while(b != 0)
{
if(b&1)
{
ans = ans * base;
ans %= mod;
}
base = base * base % mod;
b >>= 1;
}
return ans;
}
int main()
{
ll t;
cin >> t;
while(t--)
{
ll n;
cin >> n;
if(n == 0)
{
cout << 4 << endl;
continue;
}
ll k = (2 * quick_pow(3 * inv2 % mod, n) % mod + quick_pow(2, n) + 1) % mod;
cout << k << endl;
}
return 0;
}
最新文章
- Linux系统virtualbox + ubuntu + xshell 问题与注意事项
- C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
- hadoop2.6.2分布式环境搭建
- 设计模式(十四):Command命令模式 -- 行为型模式
- jQuery 图表
- 从源码解析TreeMap
- HBase架构
- 使用Putty实现windows向阿里云的Linux云服务器上传文件
- 阿里云或本地部署服务器(一)---nginx本地和服务器代理
- 虚拟机安装CentOS7(一)
- Chapter 5 Blood Type——23
- C++STL模板库关联容器之set/multiset
- java.io.FileNotFoundException:my-release-key.keyStore拒绝访问
- nginx 配置文件学习
- Android沉浸式状态栏的简单实现
- CF 449D 题解(状压+容斥)
- P1220 关路灯 (区间dp)
- 【HDOJ3861】【Tarjan缩点+最小路径覆盖】
- mybatis 插件安装与使用
- CentOS 7 Docker基本特性