[ARC104E] Random LIS 题解
[ARC104E] Random LIS 题解
Link
吐了,一下午就写了这一个题……主要是题解都说的很草率。然后上课的时候貌似讲的方法不是很能做(也许是我太菜了),总之我得写篇题解整理整理。
首先
方程:
代码:
#include<bits/stdc++.h> using namespace std; const int N = 8, mod = 1e9+7; inline int fpow(int a, int b){ int ret = 1; a%=mod; while(b){ if(b & 1){ ret = (1ll*ret*a)%mod; } b>>=1; a = (1ll*a*a)%mod; } return ret; } int a[N], b[N], na[N]; int inv[N], fac[N]; inline int C(int n, int m){ if(n<0 || m<0 || n<m) return 0; int ret = 1; for(int i = n; i>=n-m+1; --i) ret = (1ll*ret*i)%mod; return 1ll*ret*inv[m]%mod; } int n, nn; void prework(){ fac[0] = 1; for(int i = 1; i<=n; ++i){ fac[i] = (1ll*fac[i-1]*i)%mod; } inv[n] = fpow(fac[n], mod-2); for(int i = n-1; i>=0; --i){ inv[i] = (1ll*inv[i+1]*(i+1))%mod; } } bool vis[N]; int p[N];//相对位次 int dp[N]; int mx; int f[N][N];//表示第 i 个位次位于值域第 j 段的方案数。 int h[N];//每一个位次的上界 inline int calc(){ memset(h, 0x3f, sizeof(h)); int m = 0; for(int i = 1; i<=n; ++i){ h[p[i]] = min(h[p[i]], a[i]); m = max(m, p[i]); } int tot = 0; for(int i = 1; i<=m; ++i){ na[++tot] = h[i]; } sort(na+1, na+tot+1); tot = unique(na+1, na+tot+1)-na-1; for(int i = 1; i<=m; ++i){ h[i] = lower_bound(na+1, na+tot+1, h[i])-na; }//离散化 memset(f, 0, sizeof(f)); f[0][0] = 1; for(int i = 1; i<=m; ++i){ for(int j = 1; j<=h[i]; ++j){//枚举当前点选的值域 int mn = h[i]; for(int k = i; k>=1; --k){//枚举这个值域控制的范围(左端点) mn = min(h[k], mn); if(j > mn) break; for(int o = 0; o<j; ++o){ if(!f[k-1][o]) continue; f[i][j] = (1ll*f[i][j]+1ll*C(na[j]-na[j-1], i-k+1)*f[k-1][o]%mod)%mod; } } } } int ret = 0; for(int i = 1; i<=tot; ++i){ ret = (1ll*ret+f[m][i])%mod; } return ret; } int ans = 0; void dfs(int pos, int lim){ if(pos>lim){ for(int i = 1; i<=n; ++i){ b[i] = p[i]; } sort(b+1, b+n+1); for(int i = 1; i<=n; ++i){ if(b[i]-b[i-1]>1) return; } mx = 0; for(int i = 1; i<=n; ++i){ dp[i] = 1; for(int j = 1; j<i; ++j){ if(p[i]>p[j]) dp[i] = max(dp[i], dp[j]+1); } mx = max(dp[i], mx); }//dp求最长上升子序列 ans = (1ll*ans+1ll*mx*calc()%mod)%mod; return; } for(int i = 1; i<=n; ++i){ p[pos] = i; dfs(pos+1, lim); } } signed main(){ scanf("%d", &n); prework(); for(int i = 1; i<=n; ++i){ scanf("%d", &a[i]); } dfs(1, n); int innv = 1; for(int i = 1; i<=n; ++i){ innv = (1ll*innv*a[i])%mod; } innv = fpow(innv, mod-2); ans = 1ll*ans*innv%mod; ans = (ans+mod)%mod; printf("%d\n", ans); return 0; }