zoukankan      html  css  js  c++  java
  • Codeforces889C. Maximum Element

    $n leq 2000000$的排列,问有多少满足:存在个$i$,使得$p_i eq n$,且$p_j<p_i,j in [i+1,i+K]$,$K leq 2000000$是给定常数。膜$1e9+7$。

    排列题还是比较菜。。

    这次的切入点依然是排列题的经典套路--考虑将$n$加入$n-1$的合法排列,从而建立递推关系。

    先从答案要求入手,假如把$n$插进位置$i$,那么$i$之前的序列必须已经合法,否则要么接下来一个数是$n$,后面$K$个数一定$<n$,不合法,要么这序列根本就不合法,就gg。也就是说,$n$之前的数字的大小关系已经确定了。确定大小关系的情况可以开始递推:$D(i)$表示$i$在位置$i$时,剩下$i-1$个数乱排时的合法排列数——$n$(注意,这里真的是$n$)在位置$i$时,前$i-1$个数一旦确定,他们的大小关系必须如同$D(i)$的方案,然后其他的数乱排列。因此最终答案为$sum_{i=1}^{n}D(i)frac{(n-1)!}{(i-1)!}$。搞定。

    注意这里通过大小关系把$n$变成更小的东西。

    现在试着求$D(i)$。首先$i<=K$时$D(i)=0$这实际上排除了一重条件$p_i eq n$,因为此时造成$p_j<p_i,j in [i+1,i+K]$的只有非$n$的数。好那就来看看剩下最大的$n-1$。当$n-1$放在前$i-K-1$个位置时,它就是符合条件的$i$。当它放在$i-K$往后的位置时,又来!此时$n-1$后边是不可能有非法$i$了,但前面一定有,大小关系又是$D$!于是有$D(n)=(n-K-1)(n-2)!+sum_{i=n-K}^{n-1}D(i)*frac{(n-2)!}{(i-1)!}$,把$(n-2)!$提到前面,记个前缀和即可。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 //#include<queue>
     6 //#include<time.h>
     7 //#include<complex>
     8 #include<algorithm>
     9 #include<stdlib.h>
    10 using namespace std;
    11 
    12 int n,K;
    13 #define maxn 2000011
    14 const int mod=1e9+7;
    15 int fac[maxn],inv[maxn];
    16 
    17 int powmod(int a,int b)
    18 {
    19     int ans=1;
    20     while (b)
    21     {
    22         if (b&1) ans=1ll*a*ans%mod;
    23         a=1ll*a*a%mod; b>>=1;
    24     }
    25     return ans;
    26 }
    27 
    28 int sum[maxn],f[maxn];
    29 int main()
    30 {
    31     scanf("%d%d",&n,&K);
    32     fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*1ll*i%mod;
    33     inv[n]=powmod(fac[n],mod-2); for (int i=n;i>=1;i--) inv[i-1]=1ll*inv[i]*i%mod;
    34     for (int i=1;i<=K;i++) f[i]=sum[i]=0;
    35     for (int i=K+1;i<=n;i++)
    36     {
    37         f[i]=(1ll*(i-K-1)*fac[i-2]%mod+1ll*fac[i-2]*(sum[i-1]+mod-sum[i-K-1])%mod)%mod;
    38         sum[i]=(sum[i-1]+1ll*f[i]*inv[i-1])%mod;
    39     }
    40     int ans=0;
    41     for (int i=1;i<=n;i++) ans=(ans+1ll*(sum[i]-sum[i-1]+mod)*fac[n-1])%mod;
    42     printf("%d
    ",ans);
    43     return 0;
    44 }
    View Code
  • 相关阅读:
    Oracle EBS-SQL (MRP-7):检查MRP计划运行报错原因之超大数据查询2.sql
    Oracle EBS-SQL (MRP-6):检查MRP计划运行报错原因之超大数据查询1.sql
    Oracle EBS-SQL (MRP-5):重起MRP Manager.sql
    Oracle EBS-SQL (INV-12):检查待定事物处理1.sql
    Oracle EBS-SQL (OM-6):打开订单.sql
    Oracle EBS-SQL (INV-11):检查子库存会计信息.sql
    Oracle EBS-SQL (OM-5):检查订单事务处理类型.sql
    Oracle EBS-SQL (OM-4):检查发运网络.sql
    Oracle EBS-SQL (PO-18):检查工作台下达的PR在系统找不到.sql
    Oracle EBS-SQL (PO-17):检查供货比例不为100%.sql
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8576380.html
Copyright © 2011-2022 走看看