NC20894. 无畏死灵术士莉莲娜与锁链面纱
描述
「你若发现自己在遗忘边界摇摇欲坠,我的双手很乐意推上最后一把。」 ——莉莲娜维斯
输入描述
从标准输入中读入。
第一行一个正整数 n 。
第二行 n 个正整数表示一个 1 到 n 的排列。
输出描述
输出到标准输出。
一行,表示答案。对 998244353 取模。
示例1
输入:
3 2 3 1
输出:
499122178
说明:
序列初始为 {2, 3, 1} 。C++11(clang++ 3.9) 解法, 执行用时: 139ms, 内存消耗: 4464K, 提交时间: 2020-08-07 00:33:47
#include<bits/stdc++.h> using namespace std; const long long mod=998244353; int DP[1100005]={0}; int main() { int i,j,k,n,V[25],inv[25]; scanf("%d",&n); for(i=0;i<n;i++)scanf("%d",&j),V[j]=i; inv[1]=1; for(i=2;i<=n;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod; for(i=0;i<(1<<n);i++) for(j=1;j<n;j++) { if(((1<<(j-1))&i)||((1<<j)&i))continue; if(V[j]>V[j+1])DP[i]=n; } for(i=(1<<n)-1;i>=0;i--) { for(j=k=0;j<n;j++) { if(i&(1<<j))k++; else DP[i]=(DP[i]+DP[i|1<<j])%mod; } DP[i]=(long long)DP[i]*inv[n-k]%mod; } printf("%d\n",DP[0]); return 0; }
C++14(g++5.4) 解法, 执行用时: 115ms, 内存消耗: 4440K, 提交时间: 2020-08-06 19:20:53
#include<bits/stdc++.h> using namespace std; const long long mod=998244353; int DP[1100005]={0}; int main() { int i,j,k,n,V[25],inv[25]; scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&j),V[j]=i; inv[1]=1; for(i=2;i<=n;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod; for(i=0;i<(1<<n);i++) for(k=-1,j=0;j<n;j++) { if(i&(1<<j))k=-1; else { if(k>V[j+1])DP[i]=1,j=n-1; k=V[j+1]; } } for(i=(1<<n)-1;i>=0;i--) { if(DP[i])DP[i]=n; for(j=k=0;j<n;j++) { if(i&(1<<j))k++; else DP[i]=(DP[i]+DP[i|1<<j])%mod; } DP[i]=(long long)DP[i]*inv[n-k]%mod; } printf("%d\n",DP[0]); return 0; }