CF886E Maximum Element

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);
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12703361.html