noip2018 10.31 T1
T1
首先,考虑到,所要求的期望就是 可行的方案数比总方案数
很显然,对于一个点,其他点的选择对它没有影响,所以总方案数即为 $n^n$
下面,考虑可行的方案数。
经过打表,可以发现,打表什么规律都找不到。
所以我们考虑递推。
对于第n个点,有两种情况:
①前(n-1)个点已经可行,则第n个点应该形成自环。 $F[n]+=F[n-1]$
②前(n-1)个点中有(n-2)个点已经可行,则第n个点应该和剩下的点形成环。剩下的点有(n-1)个可能。 $F[n]+=(n-1)*F[n-2]$
所以我们得到递推式:
$F[n]=F[n-1]+(n-1)*F[n-2] $
然后,先预处理出 $F[n]$,然后快速幂求出 $n^n$,用exgcd求出它的逆元,膜膜膜即可。
#include<bits/stdc++.h>
#define ll long long
#define MOD 998244353
using namespace std;
int read(){
int data=0,w=1;char ch=0;
while(!isdigit(ch)){if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
ll i,j,k,l,m,n,x,y,t,ans,summ,f[600010];
ll ksm(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%MOD;
b>>=1; a=a*a%MOD;
}
return ans;
}
void exgcd(ll a,ll b){
if(!b) x=1,y=0;
else{
exgcd(b,a%b);
ll xx=x,yy=y;
x=yy;
y=xx-a/b*yy;
}
}
int main(){
t=read();
f[1]=1;f[2]=2;
for(i=3;i<=500003;++i) f[i]=(f[i-1]+((i-1)*f[i-2]%MOD))%MOD;
while(t--){
n=read();
exgcd(ksm(n,n),MOD);
while(x<0) x+=MOD;
ans=f[n]*x%MOD;
printf("%lld\n",ans);
}
return 0;
}

浙公网安备 33010602011771号