「2020-2021 集训队作业」Yet Another Permutation Problem

「2020-2021 集训队作业」Yet Another Permutation Problem

首先是否可以被构造的充要条件: 存在一段上升子串的长度$\geq $ n-k。

考虑容斥:

\(n!-\sum [所有极长上升段的长度<n-k]\)

可以记录每一个大段(合并后的段)的容斥系数和。

可以发现,只有\(t\cdot k\)的地方是-1,\(t\cdot k+1\)的地方是1,其它是0 。

用调和级数分析,背包的时间复杂度为\(O(N^2\ln N)\)

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=1e3+233;
int n,MOD,h[MAXN],fac[MAXN],rfac[MAXN],dp[MAXN];
int quick(int A,int B){
	int ret=1;
	while(B){
		if(B&1) ret=1ll*A*ret%MOD;
		B>>=1;
		A=1ll*A*A%MOD;
	}
	return ret;
}
int inv(int A){return quick(A,MOD-2);}

int main(){
	scanf("%d%d",&n,&MOD);
	fac[0]=1;
	rb(i,1,n) fac[i]=1ll*fac[i-1]*i%MOD;
	rb(i,0,n) rfac[i]=inv(fac[i]); 
	rb(i,0,n-1){
		//<n-i
		int t=n-i;
		int rest=fac[n];
		memset(dp,0,sizeof(dp));
		dp[0]=1;
		vector<mp> obj;
		for(int i=0;i<=n;i+=t){
			obj.PB({i,MOD-1});
			obj.PB({i+1,1});
		}
		rb(i,1,n){
			for(auto it:obj){
				if(it.FIR>i) break;
				(dp[i]+=1ll*dp[i-it.FIR]*it.SEC%MOD*rfac[it.FIR]%MOD)%=MOD;
			}
		}
		dp[n]=1ll*fac[n]*dp[n]%MOD;
		rest-=dp[n];
		rest+=MOD;
		rest%=MOD;
		printf("%d\n",rest);
	}
	return 0;
}
posted @ 2021-03-31 11:51  WWW~~~  阅读(204)  评论(0编辑  收藏  举报