[CF886E] Maximum Element
\(\text{Problem}:\)Maximum Element
\(\text{Solution}:\)
即求出现 \(n\) 之前还没有返回的方案数。
设 \(f_{i}\) 表示选了前 \(i\) 个位置,还没有返回的方案数,有转移:
\[\begin{aligned}
f_{i}&=\sum\limits_{j=\max(1,i-k+1)}^{i}f_{j-1}\times (i-1)^{\underline{i-j}}\\
&=(i-1)!\sum\limits_{j=\max(0,i-k)}^{i-1}\frac{f_{j}}{j!}
\end{aligned}
\]
预处理 \(\frac{f_{j}}{j!}\) 的前缀和即可在 \(O(n)\) 的时间复杂度内递推得到 \(f_{n}\)。
考虑答案为 \(n!\) 减去返回值为 \(n\) 的方案数,那么枚举 \(n\) 出现的位置,在 \(n\) 之前没有返回即合法,故有:
\[ans=n!-\sum\limits_{i=1}^{n}f_{i-1}(n-1)^{\underline{n-i}}
\]
总时间复杂度 \(O(n)\)。
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=1000010, Mod=1e9+7;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int n,K,fac[N+5],inv[N+5],f[N],qz[N];
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=1ll*x*x%Mod) if(p&1) res=1ll*res*x%Mod; return res; }
signed main()
{
fac[0]=1;
for(ri int i=1;i<=N;i++) fac[i]=1ll*fac[i-1]*i%Mod;
inv[N]=ksc(fac[N],Mod-2);
for(ri int i=N;i;i--) inv[i-1]=1ll*inv[i]*i%Mod;
n=read(), K=read();
f[0]=qz[0]=1;
for(ri int i=1;i<=n;i++)
{
int w=qz[i-1];
if(i>K) w=(w-qz[i-K-1]+Mod)%Mod;
f[i]=1ll*fac[i-1]*w%Mod;
qz[i]=(qz[i-1]+1ll*f[i]*inv[i]%Mod)%Mod;
}
int ans=0;
for(ri int i=1;i<=n;i++)
{
ans=(ans+1ll*f[i-1]*fac[n-1]%Mod*inv[i-1]%Mod)%Mod;
}
printf("%d\n",(fac[n]-ans+Mod)%Mod);
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。