zoukankan      html  css  js  c++  java
  • CF886E 题解

    题目链接

    题目大意

    从前有一个叫 (Petya) 的神仙,嫌自己的序列求(max)太慢了,于是将序列求(max)的代码改成了下面这个样子:

    int fast_max(int n,int a[])
    {
    	int ans=0;
    	int offset=0;
    	for(int i=0;i<n;++i)
    	{
    		if(ans<a[i])
    		{
    			ans=a[i];
    			offset=0;
    		}
    		else
    		{
    			offset++;
    			if(offset==k)return ans;
    		}
    	}
    	return ans;
    }
    

    新技能get
    然鹅这份代码是错的。这位(Petya)神仙对它出错的情况很感兴趣,让你求有多少 (1)~(n) 的排列,这个函数会返回错误的结果,即返回值不是 (n),输出这个数对 (10^9+7) 取模的结果。

    (Solution:)

    真是道有趣的题目呢。
    在这道题里,无论我们枚举什么东西,一个大前提显然是:此时函数并未(return)由于这是dp专题里的题,我们不妨来(dp)它。
    (f_i)表示(1)~(i)的排列中有多少个是运行完并未(return)的,那么我们考虑来枚举最大值,显然它出现在((i-k,i])这个区间中,否则会在之前(return),那么我们设最大值位置为(j),有:
    (f_i=sumlimits_{j=i-k+1}^i {f_{j-1} imes {{i-1} choose {i-j}} imes (i-j)!}),其中(f_{j-1})限制了在之前不能(return)({{i-1} choose {i-j}})意即从现在的(i-1)个位置中选出(i-j)个扔到(j)的前面,((i-j)!)即为枚举剩下位置的全排列。

    然鹅这是(O(n^2))的,我们来考虑优化。拆式子,

    (f_i=sumlimits_{j=i-k+1}^i {f_{j-1} imes {{i-1} choose {i-j}} imes (i-j)!})
    (=sumlimits_{j=i-k+1}^i {f_{j-1} imes (i-1)! imes frac{1}{(j-1)!}})
    (=sumlimits_{j=i-k+1}^i {f_{j-1} imes (i-1)! imes frac{1}{(j-1)!}})
    (=(i-1)! sumlimits_{j=i-k}^{i-1}{ frac{f_j}{j!} })

    对于(sumlimits_{j=i-k}^{i-1}{ frac{f_j}{j!} })这个东西显然可以前缀和优化一下,于是(dp)时间就缩短到(O(n))
    然后和上面差不多的分析,可以得到(ans=n!-sumlimits_{i=1}^n{f_{i-1} imes { n-1 choose n-i } imes (n-i)!})
    然后可以展开再约去一项,(ans=n!-sumlimits_{i=1}^n{f_{i-1} imes frac{(n-1)!}{(i-1)!}})
    于是用(O(n))线性预处理阶乘和阶乘的逆元,总复杂度(O(n))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    namespace my_std
    {
    	typedef long long ll;
    	typedef double db;
    	#define pf printf
    	#define pc putchar
    	#define fr(i,x,y) for(register ll i=(x);i<=(y);++i)
    	#define pfr(i,x,y) for(register ll i=(x);i>=(y);--i)
    	#define go(x) for(ll i=head[u];i;i=e[i].nxt)
    	#define enter pc('
    ')
    	#define space pc(' ')
    	#define fir first
    	#define sec second
    	#define MP make_pair
    	const ll inf=0x3f3f3f3f;
    	const ll inff=1e15;
    	inline ll read()
    	{
    		ll sum=0,f=1;
    		char ch=0;
    		while(!isdigit(ch))
    		{
    			if(ch=='-') f=-1;
    			ch=getchar();
    		}
    		while(isdigit(ch))
    		{
    			sum=sum*10+(ch^48);
    			ch=getchar();
    		}
    		return sum*f;
    	}
    	inline void write(ll x)
    	{
    		if(x<0)
    		{
    			x=-x;
    			pc('-');
    		}
    		if(x>9) write(x/10);
    		pc(x%10+'0');
    	}
    	inline void writeln(ll x)
    	{
    		write(x);
    		enter;
    	}
    	inline void writesp(ll x)
    	{
    		write(x);
    		space;
    	}
    }
    using namespace my_std;
    const ll N=1e6+50,mod=1e9+7;
    ll n,k,mul[N],inv[N],f[N],s[N];
    inline ll ksmod(ll a,ll b)
    {
    	ll ans=1;
    	while(b)
    	{
    		if(b&1)
    		{
    			ans=(ans*a)%mod;
    		}
    		a=(a*a)%mod;
    		b>>=1;
    	}
    	return ans;
    }
    inline void init(ll n)
    {
    	mul[0]=inv[0]=1;
        for(ll i=1;i<=n;i++) mul[i]=(mul[i-1]*i)%mod;
        inv[n]=ksmod(mul[n],mod-2);
        for(ll i=n-1;i;i--) inv[i]=inv[i+1]*(i+1)%mod;
    }
    inline ll C(ll n,ll m)
    {
    	if(m>n||m<0||n<0) return 0;
        ll res=inv[m]*inv[n-m]%mod;
        res=res*mul[n]%mod;
        return res;
    }
    int main(void)
    {
    	n=read(),k=read();
    	init(n);
    	f[0]=s[0]=1;
    	fr(i,1,n)
    	{
    		if(i-k-1>=0) f[i]=mul[i-1]*(s[i-1]-s[i-k-1]+mod)%mod; 
    		else f[i]=mul[i-1]*s[i-1]%mod;
    		s[i]=(s[i-1]+f[i]*inv[i])%mod;
    	}
    	ll ans=0;
    	fr(i,1,n) ans=(ans+f[i-1]*mul[n-1]%mod*inv[i-1]%mod)%mod; 
    	writeln((mul[n]-ans+mod)%mod);
    	return 0;
    }
    

    完结撒花!!!

  • 相关阅读:
    SAP:建表时如果有QUAN、CURR类型的字段不能激活的问题
    ABAP:ALV的 Header中添加HTML内容
    iframe中cookie失效问题
    让flash自动显示代码提示的两种方式
    event.srcElement说明,方法,技巧
    ABAP:FI常用BAPI
    加入收藏夹功能(jQuery)
    ABAP笔记:BDC完整版例子
    BDC处理时用到结构BDCDATA
    ABAP 自动生成EXCEL文件并作简单格式处理
  • 原文地址:https://www.cnblogs.com/lgj-lgj/p/12709733.html
Copyright © 2011-2022 走看看