【题解】Atcoder Beginner Contest226 F - Score of Permutations

F - Score of Permutations

\(\text{Soluton:}\)

首先看清题意,对于每一个置换环,球会不断轮换,直到停止。而停止轮数自然也就是所有环长的 \(\text{lcm}\) 了。

那么考虑对一个 \(\text{lcm}\) 算贡献。有一个显然的 \(dp:\)

\[f[i+j][\text{lcm}\{j,k\}]=\sum f[i][k]\times \binom{n-1-i}{j-1}\times (j-1)! \]

解释含义:设 \(f[i][j]\) 表示用 \(i\) 个点拼成所有环长的 \(\text{lcm}=j\) 的置换个数。那么考虑枚举一个长度为 \(k\) 的环贴上去:

那么我们发现,首先我们需要从剩下的点里面选出 \(k\) 个点,组成一个环。

那实际就是求了一个在剩下 \(n-i\) 个点的环排列个数,也就是 \(\binom{n-i-1}{x-1}\times (x-1)!\)

#include<bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
const int mod=998244353;
const db eps=1e-14;
inline int Max(int x,int y){return x>y?x:y;}
inline int Min(int x,int y){return x<y?x:y;}
inline db Max(db x,db y){return x-y>eps?x:y;}
inline db Min(db x,db y){return x-y<eps?x:y;}
inline int Add(int x,int y,int M=mod){return (x+y)%M;}
inline int Mul(int x,int y,int M=mod){return 1ll*x*y%M;}
inline int Dec(int x,int y,int M=mod){return (x-y+M)%M;}
inline int Abs(int x){return x<0?-x:x;}
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*w;
}
inline void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
inline int qpow(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=Mul(res,x);
		x=Mul(x,x);y>>=1;
	}
	return res;
}
typedef pair<int,int> pr;
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
const int N=2e5+10;
inline void cadd(int &x,int y){x=Add(x,y);}
namespace Refined_heart{
	int fac[N],inv[N],n,K;
	inline int C(int x,int y){return Mul(fac[x],Mul(inv[y],inv[x-y]));}
	inline int gcd(int x,int y){return !y?x:gcd(y,x%y);}
	inline int lcm(int x,int y){return x*y/gcd(x,y);}
	map<int,int>f[501];
	void solve(){
		n=read(),K=read();
		fac[0]=1;
		for(int i=1;i<=5001;++i)fac[i]=Mul(fac[i-1],i);
		inv[5001]=qpow(fac[5001],mod-2);
		for(int i=5001;i;--i)inv[i-1]=Mul(inv[i],i);
		f[0][1]=1;
		for(int i=0;i<n;++i){
			for(auto &[key,val]:f[i]){
				for(int j=1;j+i<=n;++j){
					cadd(f[i+j][lcm(key,j)],Mul(val,Mul(fac[j-1],C(n-i-1,j-1))));
				}
			}
		}
		int ans=0;
		for(auto &[key,val]:f[n])cadd(ans,Mul(val,qpow(key,K)));
		printf("%lld\n",ans);
	}
}
signed main(){
	Refined_heart::solve();
	return 0;
}
posted @ 2021-11-08 16:36  Refined_heart  阅读(73)  评论(0编辑  收藏  举报