DTOJ 4019 白玉楼前
程序员文章站
2022-03-23 11:36:19
...
白玉楼前
【题目背景】
“一觉醒来怎么半灵又不见了?一定是幽幽子吃了。”
“幽幽子你给我吐出来!”
“我这边有个游戏玩不过去,你帮我玩过去我就吐出来。”
【题目描述】
妖梦现在要玩幽幽子的游戏,她才能拿回自己的半灵。
游戏规则是这样的:
幽幽子有 个点,现在她让妖梦对每个点随机一条出边(随机到每个点的概率都相等),
然后得到一张图。(注意:可以自环)
如果这张图任意一个点沿着边走两步(显然这样的走法唯一)都能到达自身,则幽幽子可以通关。
现在幽幽子想问妖梦,她通关的概率是多少?
两个图不同,当且仅当存在一条边出现在图A 中且不出现在图B 中。图中的点有编号,边无编号。
答案
【输入格式】
第一行一个数 表示数据组数:
下面T 行,每行中只有一个数,表示。
【输出格式】
输出T 行,每行一个数表示答案。
【样例输入】
1
1
【样例输出】
1
【样例解释】
只有 这种情况,且符合题意。
【数据范围】
题解:(最近是出题人比较喜欢东方吧QAQ,上次是兔子,这次就成幽幽子了。。)
问题就是转化为求一个排列的对偶排列个数。
先考虑方案数。
设表示合法的方案数。
对于一个个点的图,考虑对于第 个点,可以有两种情况,
一个是它单独形成了一个自环,一个是与前个点中的一个点手牵手形成一个环,就剩下个点的方案惹。。。
//orzlkw
#include<bits/stdc++.h>
using namespace std;
#define in inline
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
#define For(i,a,b) for(int i=a;i<b;i++)
#define _(d) while(d(isdigit(ch=getchar())))
#define shenben puts("orzlkw");
template<class T>in void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
typedef long long ll;
const ll mod=998244353;
const int N=5e5+233,L=5e5;
ll f[N];
in ll qp(ll x,ll y){
ll res=1;x%=mod;
while(y){
if(y&1) res=res*x%mod;
x=x*x%mod;y>>=1;
}return res%mod;
}
in ll inv(ll x){
return qp(x,mod-2);
}
int main(){
freopen("youmu.in","r",stdin);freopen("youmu.out","w",stdout);
f[1]=1,f[2]=2;
rep(i,3,L) f[i]=(f[i-1]+(i-1)*f[i-2]%mod)%mod;
int T;g(T);
while(T--){
ll x;g(x);
ll sum=qp(x,x)%mod;
ll ans=f[x]*inv(sum)%mod;
printf("%lld\n",(ans%mod+mod)%mod);
}
return 0;
}
推荐阅读