欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DTOJ 4019 白玉楼前

程序员文章站 2022-03-23 11:36:19
...

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

【数据范围】
T5×105,n5×105T \leq 5\times 10^5,n\leq 5\times 10^5

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

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

先考虑方案数。
fif_{i}表示合法的方案数。
对于一个n1n-1个点的图,考虑对于第nn 个点,可以有两种情况,
一个是它单独形成了一个自环,一个是与前i1(i-1)个点中的一个点手牵手形成一个环,就剩下(i2)(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;
}
相关标签: 数学 测试题解