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

F - Score of Permutations

Soluton:

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

那么考虑对一个 lcm 算贡献。有一个显然的 dp:

f[i+j][lcm{j,k}]=f[i][k]×(n1ij1)×(j1)!

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

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

那实际就是求了一个在剩下 ni 个点的环排列个数,也就是 (ni1x1)×(x1)!

#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 @   Refined_heart  阅读(74)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示