题解 Hill of Sunflowers
读错题了,以为是每种可能的 b 数组中的所有 LIS 都能分别产生一次贡献
最后发现模不出来样例,手玩了个 \(n=3\) 跑路
发现 \(n\) 较小,可以直接枚举最终 b 数组的大小关系
具体地,可以枚举出所有可能的 \(b_i\) 的最终排名 \(p_i\)
则问题变为每个 \(b\) 有个 \(b_i\leqslant lim_i\) 的限制,要给所有 \(b_i\) 赋权值
令 \(f_{i, j}\) 为给第 \(i\) 大数赋值且值在离散化后第 \(j\) 个区间中的方案数
转移枚举上一个不在此区间内的数,组合数把中间的数放到当前区间里即可
复杂度 \(O(4683n^4)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 10
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N];
const int mod=1e9+7;
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
namespace force{
int b[N], f[N], ans;
void calc() {
f[0]=0;
int max_len=0;
for (int i=1; i<=n; ++i) {
int maxn=0;
for (int j=0; j<i; ++j) if (b[j]<b[i]) maxn=max(maxn, f[j]);
max_len=max(max_len, f[i]=maxn+1);
}
ans=(ans+max_len)%mod;
}
void dfs(int u) {
if (u>n) {calc(); return ;}
for (int i=1; i<=a[u]; ++i) {
b[u]=i;
dfs(u+1);
}
}
void solve() {
dfs(1);
ll inv=1;
for (int i=1; i<=n; ++i) inv=inv*a[i]%mod;
printf("%lld\n", ans*qpow(inv, mod-2)%mod);
}
}
namespace task1{
ll inv[N];
ll qsum(ll n) {return n*(n+1)%mod*inv[2]%mod;}
ll C(ll n, ll k) {
if (n<k) return 0;
else if (k==2) return n*(n-1)%mod*inv[2]%mod;
else if (k==3) return n*(n-1)%mod*(n-2)%mod*inv[6]%mod;
else assert(0);
return 0;
}
ll solve(int a, int b) {return (a*(b-a)%mod+qsum(a-1))%mod;}
ll solve(int a, int b, int c) {
ll ans=0;
ans=(ans+solve(a, b)*(c-b))%mod;
ans=(ans+C(a, 2)*(b-a))%mod;
ans=(ans+C(b-a, 2)*a)%mod;
ans=(ans+C(a, 3))%mod;
return ans;
}
void solve() {
inv[0]=inv[1]=1;
for (int i=2; i<=10; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
ll ans=0, all=0, tmp=0;
if (n==1) ans=a[1];
else if (n==2) ans=(2*solve(min(a[1], a[2]), a[2])+a[1]*a[2]-solve(min(a[1], a[2]), a[2]))%mod;
else {
all=a[1]*a[2]%mod*a[3]%mod;
if (a[1]<=a[2] && a[2]<=a[3]) {
//cout<<1<<endl;
ans=(ans+3*solve(a[1], a[2], a[3]))%mod;
all=(all-solve(a[1], a[2], a[3]))%mod;
tmp=(solve(a[1], a[1], a[1])+2*solve(a[1], a[1])+a[1])%mod;
ans=(ans+tmp)%mod; all=(all-tmp)%mod;
ans=(ans+2*all)%mod;
}
else if (a[1]>=a[2] && a[2]<=a[3]) {
//cout<<2<<endl;
ans=(ans+3*solve(a[2], a[2], a[3]))%mod;
all=(all-solve(a[2], a[2], a[3]))%mod;
tmp=(solve(a[2], a[2], a[1])+solve(a[2], a[1])+solve(a[2], a[2])+a[2])%mod;
ans=(ans+tmp)%mod; all=(all-tmp)%mod;
ans=(ans+2*all)%mod;
}
else if (a[1]<=a[2] && a[2]>=a[3]) {
//cout<<3<<endl;
ans=(ans+3*solve(min(a[1], a[3]), a[3], a[3]))%mod;
all=(all-solve(min(a[1], a[3]), a[3], a[3]))%mod;
tmp=(solve(min(a[1], a[3]), a[1], a[1])+2*solve(min(a[1], a[3]), a[1])+min(a[1], a[3]));
ans=(ans+tmp)%mod; all=(all-tmp)%mod;
ans=(ans+2*all)%mod;
}
else if (a[1]>=a[2] && a[2]>=a[3]) {
//cout<<4<<endl;
ans=(ans+3*solve(a[3], a[3], a[3]))%mod;
all=(all-solve(a[3], a[3], a[3]))%mod;
tmp=(solve(a[3], a[2], a[1])+solve(a[3], a[1])+solve(a[3], a[2])+a[3]);
ans=(ans+tmp)%mod; all=(all-tmp)%mod;
ans=(ans+2*all)%mod;
}
}
ll prod=1;
for (int i=1; i<=n; ++i) prod=prod*a[i]%mod;
printf("%lld\n", (ans*qpow(prod, mod-2)%mod+mod)%mod);
}
}
namespace task{
bool vis[N];
int b[N], p[N], f[N], lim[N], uni[N], usiz;
ll inv[N], dp[N][N], ans;
ll C(ll n, int k) {if (n<k) return 0; ll ans=inv[k]; for (ll i=n; i>n-k; --i) ans=ans*i%mod; return ans;}
ll calc() {
//cout<<"calc: "; for (int i=1; i<=n; ++i) cout<<p[i]<<' '; cout<<endl;
int m=0; usiz=0;
memset(lim, 127, sizeof(lim));
memset(dp, 0, sizeof(dp));
for (int i=1; i<=n; ++i) lim[p[i]]=min(lim[p[i]], a[i]), m=max(m, p[i]);
for (int i=1; i<=n; ++i) uni[++usiz]=lim[p[i]];
sort(uni+1, uni+usiz+1);
usiz=unique(uni+1, uni+usiz+1)-uni-1;
//cout<<"uni: "; for (int i=1; i<=usiz; ++i) cout<<uni[i]<<' '; cout<<endl;
dp[0][0]=1;
for (int i=1; i<=m; ++i)
for (int j=1; j<=usiz&&uni[j]<=lim[i]; ++j) {
int down=lim[i];
for (int k=i-1; ~k; --k) {
down=min(down, lim[k+1]);
if (down<uni[j]) break;
for (int l=0; l<j; ++l)
dp[i][j]=(dp[i][j]+dp[k][l]*C(uni[j]-uni[j-1], i-k))%mod;
}
}
//cout<<"---dp---"<<endl; for (int i=1; i<=m; ++i) {for (int j=1; j<=usiz; ++j) cout<<dp[i][j]<<' '; cout<<endl;}
ll ans=0;
for (int i=1; i<=usiz; ++i) ans=(ans+dp[m][i])%mod;
//cout<<"return: "<<ans<<endl<<endl;
return ans;
}
void dfs(int u) {
if (u>n) {
int maxn=0, max_len=0;
memset(vis, 0, sizeof(vis));
for (int i=1; i<=n; ++i) vis[p[i]]=1, maxn=max(maxn, p[i]);
for (int i=maxn; i; --i) if (!vis[i]) return ;
for (int i=1; i<=n; ++i) {
int maxn=0;
for (int j=1; j<i; ++j) if (p[j]<p[i]) maxn=max(maxn, f[j]);
max_len=max(max_len, f[i]=maxn+1);
}
ans=(ans+max_len*calc())%mod;
return ;
}
for (int i=1; i<=n; ++i) p[u]=i, dfs(u+1);
}
void solve() {
inv[0]=inv[1]=1;
for (int i=2; i<N; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<N; ++i) inv[i]=inv[i-1]*inv[i]%mod;
dfs(1);
//cout<<ans<<endl; return ;
ll prod=1;
for (int i=1; i<=n; ++i) prod=prod*a[i]%mod;
printf("%lld\n", (ans*qpow(prod, mod-2)%mod+mod)%mod);
}
}
signed main()
{
freopen("hill.in", "r", stdin);
freopen("hill.out", "w", stdout);
n=read();
for (int i=1; i<=n; ++i) a[i]=read()%mod;
// force::solve();
task::solve();
return 0;
}