CF1603E A Perfect Problem
注:完美为 perfect,好的为 good。好的序列为
首先,我们考虑排好序的完美序列,任意完美的序列的任意排列都是完美的。
然后我们发现:
定理 1 一个排好序的序列是完美的当且仅当其每个子区间都是好的。
证明:枚举每个
定理 2 一个排好序的序列是完美的当且仅当其每个前缀都是好的。
证明:此时,
定理 3
证明:若
定理 4 若
证明:由定理 2
定理 5 若
证明:
分两个情况讨论
但是,我们要求的序列是没有排序的,让我们把每个数都减去
枚举
-
-
- 至少存在
i(1\le i\le n-a_1) 个数\ge n+2-i-a_1 。
我们设
DP 应该是
定理 6
证明:因为条件至少存在
复杂度
#include<cstdio>
#include<cmath>
#include<algorithm>
typedef unsigned long long ull;
typedef __uint128_t L;
struct FastMod {
ull b, m;
FastMod(ull b) : b(b), m(ull((L(1) << 64) / b)) {}
ull operator ()(ull a) {
ull q = (ull)((L(m) * a) >> 64);
ull r = a - q * b; // can be proven that 0 <= r < 2*b
return r >= b ? r - b : r;
}
}mod(2);
int p,n,fac[210],ifac[210];
int pow(int x,int y){
int res=1;
while(y){
if(y&1) res=mod(1ll*res*x);
x=mod(1ll*x*x),y>>=1;
}
return res;
}
int main(){
scanf("%d%d",&n,&p);
mod=FastMod(p);
fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=mod(1ll*fac[i-1]*i);
ifac[n]=pow(fac[n],p-2);
for(int i=n;i;i--) ifac[i-1]=mod(1ll*ifac[i]*i);
int ans=0;
int lim=2*sqrt(n)+1;
for(int a1=std::max(1,n-lim);a1<=n;a1++){
static int f[210][210][210];
for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=0;k<=n;k++) f[i][j][k]=0;
for(int i=0;i<=n;i++)
for(int sum=0;sum<=a1;sum++)
f[i][sum][0]=mod(1ll*fac[n]*ifac[n-i]);
for(int k=1;k<=n+1-a1;k++){
for(int i=0;i<n;i++)
for(int sum=0;sum<=a1;sum++){
int &ans=f[i][sum][k];
int r=(a1-sum)/k;
for(int cnt=std::min(r,n-i);~cnt;--cnt)if(k<=1||i+cnt>=n-a1+2-k){
ans=mod(ans+1ll*f[i+cnt][sum+cnt*k][k-1]*ifac[cnt]);
}
}
for(int sum=0;sum<=a1;sum++) f[n][sum][k]=fac[n];
}
ans=mod(ans+f[0][0][n+1-a1]);
}
printf("%d\n",ans);
return 0;
}