强军如歌(strong)
强军如歌(strong)
题目描述
给定一个NN个数的序列AA,如果序列AA不是非降序的,你需要在其中选择一个数删掉,不断重复这个操作直到序列AA非降。求有多少种不同的删数方案。注意:删掉的数的集合相同,但是删数的顺序不同,视作不同的删数方案。
输入
第一行一个数NN。
接下来一行NN个正整数,用空格隔开,第ii个数表示Ai。
输出
一行一个整数表示答案对1000000007取模的结果。
solution
首先我们考虑不管删数顺序,枚举出剩下的不降序列。
假设长度为l
那么这时候的删数方案为(n-l)!
我们考虑一种不合法的删数方案:再删除第l个数前,序列一定要是不降的。
也就是每一个长度为l+1的不降序列,都对应着l+1个不合法方案。
用树状数组求出长度为l的不降子序列个数
这样就可以快速统计了
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 2005
#define mod 1000000007
#define ll long long
using namespace std;
int n,Max,a[maxn];
ll f[maxn][maxn],tree[maxn],ans[maxn],h[maxn];
int ask(int i){
ll sum=0;
for(;i;i-=i&-i)sum=(sum+tree[i])%mod;
return sum;
}
void jia(int i,ll v){
for(;i<=Max;i+=i&-i)tree[i]=(tree[i]+v)%mod;
}
int main()
{
cin>>n;
h[0]=1;for(int i=1;i<=n;i++)h[i]=(h[i-1]*i)%mod;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
Max=max(a[i],Max);
}
for(int i=1;i<=n;i++)f[i][1]=1;ans[1]=h[n];
for(int i=2;i<=n;i++){
for(int j=1;j<=Max;j++)tree[j]=0;
for(int j=1;j<=n;j++){
f[j][i]=ask(a[j]);
jia(a[j],f[j][i-1]);
}
ll sum=0;
for(int j=1;j<=n;j++)sum=(sum+f[j][i])%mod;
ans[i]=(sum*h[n-i])%mod;
}
ll A=0;
for(int i=1;i<=n;i++){
A=A+ans[i]-(ans[i+1]*(i+1))%mod;A%=mod;
}
A=(A%mod+mod)%mod;
cout<<A<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构