DTOJ 4019 白玉楼前

版权声明:神犇使用记得标明出处哦QAQ https://blog.csdn.net/qq_41717018/article/details/83621189

白玉楼前
【题目背景】
“一觉醒来怎么半灵又不见了?一定是幽幽子吃了。”
“幽幽子你给我吐出来!”
“我这边有个游戏玩不过去,你帮我玩过去我就吐出来。”
【题目描述】
妖梦现在要玩幽幽子的游戏,她才能拿回自己的半灵。
游戏规则是这样的:
幽幽子有 n n 个点,现在她让妖梦对每个点随机一条出边(随机到每个点的概率都相等),
然后得到一张图。(注意:可以自环)
如果这张图任意一个点沿着边走两步(显然这样的走法唯一)都能到达自身,则幽幽子可以通关。
现在幽幽子想问妖梦,她通关的概率是多少?
两个图不同,当且仅当存在一条边出现在图A 中且不出现在图B 中。图中的点有编号,边无编号。
答案 m o d mod 998244353 998244353
【输入格式】
第一行一个数 T T 表示数据组数:
下面T 行,每行中只有一个数,表示 n n
【输出格式】
输出T 行,每行一个数表示答案。
【样例输入】
1
1
【样例输出】
1
【样例解释】
只有 1 > 1 1->1 这种情况,且符合题意。

【数据范围】
T 5 × 1 0 5 , n 5 × 1 0 5 T \leq 5\times 10^5,n\leq 5\times 10^5

题解:
(最近是出题人比较喜欢东方吧QAQ,上次是兔子,这次就成幽幽子了。。)

问题就是转化为求一个排列的对偶排列个数。

先考虑方案数。
f i f_{i} 表示合法的方案数。
对于一个 n 1 n-1 个点的图,考虑对于第 n n 个点,可以有两种情况,
一个是它单独形成了一个自环,一个是与前 i 1 (i-1) 个点中的一个点手牵手形成一个环,就剩下 ( i 2 ) (i-2) 个点的方案惹。。。

//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;
}

猜你喜欢

转载自blog.csdn.net/qq_41717018/article/details/83621189
今日推荐