【2023.10.25】NOIP2023模拟试题-24
T1
题目大意
给定长度为
思路分析
稍微手推一下可以发现最大值更小的限制不受最大值更大的限制影响,而且最大值最小的几行(列)一定是完整的,所以我们可以从最小的开始计算组合数,每次算完就删除这一行(列),来保证下一个要计算的行(列)也是完整的。
比如这个表,最小的
b\a | 3 | 1 | 4 |
---|---|---|---|
3 | 3 | 1 | 3 |
2 | 2 | 1 | 2 |
4 | 3 | 1 | 4 |
b\a | 3 | 4 |
---|---|---|
3 | 3 | 3 |
2 | 2 | 2 |
4 | 3 | 4 |
然后删掉
b\a | 3 | 4 |
---|---|---|
3 | 3 | 3 |
4 | 3 | 4 |
然后删掉
接下来我们考虑怎么用容斥计算值相同的多行多列的组合方式,最终的答案
假设有
考虑用容斥原理计算这些限制的贡献,枚举
展开代码
#include<bits/stdc++.h>
using namespace std;
#define N 2005
#define Z 10005
#define P 1000000009
#define ll long long
ll qpow(ll a,ll b){
ll c=1;
while(b){
if(b&1)c=c*a%P;
b>>=1;
a=a*a%P;
}
return c;
}
ll inv(ll x){
return qpow(x,P-2);
}
ll fac[Z];
ll C(ll n,ll m){
return fac[n]*inv(fac[m])%P*inv(fac[n-m])%P;
}
int a[N],b[N],n,m;
ll fa[Z],fb[Z];
ll ans=1,jied;
int main(){
freopen("mat.in","r",stdin);
freopen("mat.out","w",stdout);
scanf("%d",&n);
fac[0]=1;
for(int i=1;i<Z;++i){
fac[i]=fac[i-1]*i%P;
}
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
++fa[a[i]];
}
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d",&b[i]);
++fb[b[i]];
}
for(int c=0;c<Z;++c){
if(fa[c]+fb[c]>0){
jied=0;
ll ara=(fa[c]*m+fb[c]*n-fa[c]*fb[c])%P;
ll niet,f,tmp;
for(ll i=0;i<=fa[c];++i){
for(ll j=0;j<=fb[c];++j){
niet=i*m+j*n-i*j;
f=(((i+j)&1)==1?-1:1);
tmp=C(fa[c],i)*C(fb[c],j)%P*qpow(c+1,(ara-niet)%P)%P*qpow(c,niet)%P;
// printf("值=%d 行=%lld/%lld 列=%lld/%lld 组合=%lld\n",c,j,fb[c],i,fa[c],f*tmp);
jied=(jied+tmp*f+P)%P;
}
}
n-=fa[c],m-=fb[c];
ans=ans*jied%P;
}
}
printf("%lld",ans);
return 0;
}
T3 [ JOI Open 2018] 冒泡排序 2
题目描述
冒泡排序是一个对序列排序的算法。现在我们要将一个长度为
JOI 君有一个长度为
JOI 君想知道处理每次修改之后,用冒泡排序的扫描趟数。
思路分析
维护每个数之前的比他大的数的个数,全局最大值就是答案。
为啥呢?这些比他大的数都要到他右边去,一趟最多带一个过去,所以个数就是趟数。
考虑
修改定义后的
接下来考虑怎么维护权值线段树。
我们只需要维护每一个数字的 ƒ 就行了。具体地,我们发现删除一个数时,这个数对应的线段树节点存储的
展开代码
#include<bits/stdc++.h>
using namespace std;
#define N 1500005
#define time tptptp
#define fs fsyfsy
#define tm tmmtmt
#define x0 weti36
#define x1 fdsuhg
#define y0 igriog
#define y1 nsoggn
#define ws jioreo
#define id gjidfi
#define prev fjfjfj
#define next gjoire
#define at aegvji
#define in inindf
#define qi russia
#define qn etytyj
#define rank hfwehi
#define heap hiphop
int m;
int n;
pair<int,int>a[N],poi[N*5];
int at[N],pcnt,qi[N],qn[N],pre[N];
struct node{
int l,r;
int mx,add;
}tr[N*32];
#define lson(x) ((x)<<1)
#define rson(x) (lson(x)|1)
#define Lson(x) tr[lson(x)]
#define Rson(x) tr[rson(x)]
struct TREE{
void pushdown(int x){
if(tr[x].l==tr[x].r)return;
if(tr[x].add==0)return;
Lson(x).add+=tr[x].add;
Rson(x).add+=tr[x].add;
Lson(x).mx+=tr[x].add;
Rson(x).mx+=tr[x].add;
tr[x].add=0;
return;
}
void pushup(int x){
if(tr[x].l==tr[x].r)return;
tr[x].mx=max(Lson(x).mx,Rson(x).mx);
}
void build(int x,int l,int r){
tr[x].l=l;tr[x].r=r;
if(l==r)return;
int mid=(l+r)>>1;
build(lson(x),l,mid);
build(rson(x),mid+1,r);
pushup(x);
return;
}
void update(int x,int l,int r,int val){
if(tr[x].l>r||tr[x].r<l)return;
if(tr[x].l>=l&&tr[x].r<=r){
tr[x].add+=val;
tr[x].mx+=val;
return;
}
pushdown(x);
update(lson(x),l,r,val);
update(rson(x),l,r,val);
pushup(x);
}
void out(int x,int lev){
pushdown(x);
for(int i=1;i<lev;++i)putchar('\t');
printf("[%d,%d] : mx=%d\n",tr[x].l,tr[x].r,tr[x].mx);
if(tr[x].l==tr[x].r)return;
out(lson(x),lev+1);
out(rson(x),lev+1);
return;
}
}tree;
int main(){
// freopen("sort.in","r",stdin);
// freopen("sort.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&a[i].first);
a[i].second=i;
poi[++pcnt]=a[i];
}
for(int i=1;i<=m;++i){
scanf("%d %d",&qi[i],&qn[i]);
++ qi[i];
poi[++pcnt]=make_pair(qn[i],i+n);
}
sort(poi+1,poi+pcnt+1);
for(int i=1;i<=pcnt;++i){
if(poi[i].first==poi[i-1].first){
pre[i]=pre[i-1];
}else{
pre[i]=i;
}
}
tree.build(1,1,pcnt);
for(int i=1;i<=n;++i){
int id=lower_bound(poi+1,poi+pcnt+1,a[i])-poi;
tree.update(1,id,id,i);
tree.update(1,pre[id],pcnt,-1);
}
// tree.out(1,1);
for(int i=1;i<=m;++i){
int id=lower_bound(poi+1,poi+pcnt+1,a[qi[i]])-poi;
tree.update(1,id,id,-qi[i]);
tree.update(1,pre[id],pcnt,1);
a[qi[i]]=make_pair(qn[i],n+i);
id=lower_bound(poi+1,poi+pcnt+1,a[qi[i]])-poi;
tree.update(1,id,id,qi[i]);
tree.update(1,pre[id],pcnt,-1);
printf("%d\n",tr[1].mx);
// tree.out(1,1);
}
return 0;
}
return;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】