[笔记]自己想的一个题,解题思路以及代码
自己在学校想到的,很大概率是已经存在的原题,不过这道题很有趣,所以记录一下
题意简述
输入一个\(N\),询问\(\{1,2,…,N\}\)的所有全排列中满足下列条件的排列\(P\)的个数取模\(998244353\)的值:
- 定义\(A\)数组,初始全为空。对于\(1\leq i\leq N\),设\(A_{P_i}\)为\(i\)。如果\(A=P\),则满足条件。
说明:\(1\leq N \leq 10^7\)
样例及解释
Input: 3 Output: 4
\(\{1,2,3\}\)的全排列有\(\{1,2,3\},\{1,3,2\},\{2,1,3\},\{2,3,1\},\{3,1,2\},\{3,2,1\}\)。
依照规则填写的\(A\)分别是\(\{1,2,3\},\{1,3,2\},\{2,1,3\},\textcolor{red}{\{3,1,2\}},\textcolor{red}{\{2,3,1\}},\{3,2,1\}\)。
红色的是不匹配的,于是答案为\(4\)。
解题思路
根据题意,满足条件必须要求\(A_i=P_i,A_{P_i}=i\)
\(A_i=P_i\)即\(A_{P_i}=P_{P_i}\)
又因为\(A_{P_i}=i\),所以\(P_{P_i}=i\)
满足\(P_{P_i}=i\)的\(P\)即为符合条件,接下来我们用dp解决。
设\(dp_i\)为\(N=i\)时的答案,初始\(dp_1=1,dp_2=2\)。
递推式:\(dp_i=dp_{i-1}+(i-1)*dp_{i-2}\)
怎么推导的呢?我画个图,通过\(N=4\)的情况解释:
下面附上代码实现↓
Code
可以用滚动数组优化空间。(懒)
#include<bits/stdc++.h> #define int long long #define mod 998244353 using namespace std; int n,dp[10000010]; signed main(){ cin>>n; dp[1]=1,dp[2]=2; for(int i=3;i<=n;i++){ dp[i]=(dp[i-1]+((i-1)*dp[i-2])%mod)%mod; } cout<<dp[n]; return 0; }
\[[THE\ \ END]
\]
注:若发现错误或改进建议,请在评论区指出,感谢万分!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效