白玉楼前
白玉楼前
【题目背景】
“一觉醒来怎么半灵又不见了?一定是幽幽子吃了。”
“幽幽子你给我吐出来!”
“我这边有个游戏玩不过去,你帮我玩过去我就吐出来。”
【题目描述】
妖梦现在要玩幽幽子的游戏,她才能拿回自己的半灵。
游戏规则是这样的:
幽幽子有n nn 个点,现在她让妖梦对每个点随机一条出边(随机到每个点的概率都相等),
然后得到一张图。(注意:可以自环)
如果这张图任意一个点沿着边走两步(显然这样的走法唯一)都能到达自身,则幽幽子可以通关。
现在幽幽子想问妖梦,她通关的概率是多少?
两个图不同,当且仅当存在一条边出现在图A 中且不出现在图B 中。图中的点有编号,边无编号。
答案mod 998244353
【数据范围】
T≤5×105,n≤5×105 T \leq 5\times 10^5,n\leq 5\times 10^5T≤5×10
solution
本题求1~n的排列的对偶排列个数,即满足p[p[i]]=i的p[i]个数.
令f[i]表示前i个数的答案
f[i]=f[i-1]+(i-1)*f[i-2];
也就是它可以和自己对偶p[i]=i;
或者和任意一个人(i-1) 乘上 i-2个人的答案
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 500005
#define ll long long
#define mod 998244353
using namespace std;
int n;
ll f[maxn],ny[maxn];
ll work(ll a,int num){
ll p=a,x=1;
while(num){
if(num&1)x=x*p;
p=p*p;p%=mod;x%=mod;num>>=1;
}
return x;
}
int main()
{
freopen("youmu.in","r",stdin);
freopen("youmu.out","w",stdout);
n=500000;
f[0]=1;f[1]=1;
for(int i=2;i<=n;i++){
f[i]=f[i-1]+(ll)(i-1)*f[i-2]%mod;f[i]%=mod;
}
for(int i=0;i<=n;i++){
ny[i]=work(work(i,i),mod-2);
}
int T;
cin>>T;
for(int i=1;i<=T;i++){
scanf("%d",&n);
ll ans=ny[n]*f[n];ans=(ans%mod+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构