Link
不难发现,返回值错误当且仅当在(n)的前面,存在连续的(k)个数,使得这(k)个数均小于这(k)个数前面的最大值。
设(f_i)表示长度为(i)的未由if(offset==k)return ans;
返回的排列个数。
枚举(i)所在的位置(j),转移为(f_i=sumlimits_{j=i-k+1}^if_{j-1}{i-1choose i-j}(i-j)!=(i-1)!sumlimits_{j=i-k}^{i-1}frac{f_j}{j!})。
设(g_i=frac{f_i}{i!}),那么(g_i=frac{sumlimits_{j=i-k}^{i-1}g_j}i),前缀和优化即可。
最后(ans=n!-sumlimits_{i=1}^nf_{i-1}{n-1choose n-i}(n-i)!=(n-1)!(n-sumlimits_{i=1}^ng_{i-1}))。
#include<cstdio>
const int N=1000007,P=1000000007;
int inv[N],f[N];
int main()
{
int n,m,fac=1;scanf("%d%d",&n,&m),inv[0]=inv[1]=1;
if(n<=m) m=n-1;
for(int i=2;i<n;++i) inv[i]=1ll*(P-P/i)*inv[P%i]%P,fac=1ll*i*fac%P;
for(int i=0;i<=m;++i) f[i]=i+1;
for(int i=m+1;i<n;++i) f[i]=(1ll*(f[i-1]-f[i-m-1]+P)*inv[i]+f[i-1])%P;
printf("%lld",1ll*fac*(n-f[n-1]+P)%P);
}