zoukankan      html  css  js  c++  java
  • 【CF886E】Maximum Element

    题面

    洛谷

    题解

    (f_i)表示(i)个数的排列,最大的数填在了最后一个位置,且这个( ext{fast_max})函数尚未返回的方案数。

    枚举数(i-1)的位置,那么(i-1)必然填在区间([i-k,i-1])内,否则函数就会返回。

    那么我们有

    [egin{aligned} f_i&=sum_{j=i-k}^{i-1}f_j imes (i-j-1)! imes {j-1 choose i - 2}\ &=sum_{j=i-k}^{i-1}frac{(i-2)!}{(j-1)!}f_j end{aligned} ]

    你记一个(frac{f_j}{(j-1)!})的前缀和就可以(O(n))求出所有(f)了。

    最后算答案你就枚举最大数所在位置然后和算(f)的原理相同,就是

    [Ans=sum_{i=1}^nf_i imes {n-1choose i-1} imes (n-i)! ]

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std; 
    const int Mod = 1e9 + 7; 
    const int MAX_N = 1e6 + 5; 
    int fpow(int x, int y) { 
    	int res = 1; 
    	while (y) { 
    		if (y & 1) res = 1ll * res * x % Mod; 
    		x = 1ll * x * x % Mod; 
    		y >>= 1; 
    	} 
    	return res; 
    } 
    int N, K, fac[MAX_N], ifc[MAX_N]; 
    int f[MAX_N], s[MAX_N]; 
    int main () { 
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin); 
    #endif 
    	cin >> N >> K; 
    	fac[0] = 1; for (int i = 1; i <= N; i++) fac[i] = 1ll * fac[i - 1] * i % Mod; 
    	ifc[N] = fpow(fac[N], Mod - 2); 
    	for (int i = N - 1; ~i; i--) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % Mod;
    	f[1] = s[1] = 1; 
    	for (int i = 2; i <= N; i++) { 
    		f[i] = 1ll * fac[i - 2] * (s[i - 1] - s[max(0, i - K - 1)] + Mod) % Mod; 
    		s[i] = (s[i - 1] + 1ll * f[i] * ifc[i - 1]) % Mod; 
    	} 
    	int ans = (fac[N] - 1ll * s[N] * fac[N - 1] % Mod + Mod) % Mod; 
    	printf("%d
    ", ans); 
        return 0; 
    } 
    
  • 相关阅读:
    .net 中ifram的session过期,跳转到登录页面
    新建物料组!
    WCF学习系列(1)
    WCF学习系列(4)————数据协定
    AX中操作Excel
    WCF学习系列(3)————承载
    简单的库存模型组
    博弈_ZOJ3591_序列中子序列异或值大于0.cpp
    zoj2527_求最长等差数列
    第二次周日赛
  • 原文地址:https://www.cnblogs.com/heyujun/p/12198904.html
Copyright © 2011-2022 走看看