T1 宝藏

发现每个数成为中位数的长度是关于权值单调的。线段树二分判断是否合法,单调指针扫即可。

考场上写了二分,平添\(\log\)。

\(code:\)

T1
#include<bits/stdc++.h>
using namespace std; namespace IO{
typedef long long LL;
LL read(){
LL x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
void write(int x,char sp){
char ch[20]; int len=0;
if(x<0) x=-x,putchar('-');
do{ ch[len++]=x%10+'0'; x/=10; }while(x);
for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
}
void ckmin(int& x,int y){ x=x<y?x:y; }
void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO; const int NN=300010;
int n,x,Q,ext,has[NN],ans[NN];
struct node{
int w,t;
bool operator<(const node& a)const{
return w<a.w;
}
}p[NN];
LL T; struct segmengt_tree{
#define ld rt<<1
#define rd (rt<<1)|1
int num[NN<<2];
LL sum[NN<<2];
void pushup(int rt){
num[rt]=num[ld]+num[rd];
sum[rt]=sum[ld]+sum[rd];
}
void update(int rt,int l,int r,int pos,int typ){
if(l==r){
num[rt]+=typ; sum[rt]+=typ*has[pos];
return;
}
int mid=l+r>>1;
if(pos<=mid) update(ld,l,mid,pos,typ);
else update(rd,mid+1,r,pos,typ);
pushup(rt);
}
LL query(int rt,int l,int r,int lmt){
if(!lmt) return 0;
if(num[rt]<=lmt) return sum[rt];
if(l==r) return 1ll*has[l]*lmt;
int mid=l+r>>1;
if(num[ld]>=lmt) return query(ld,l,mid,lmt);
return sum[ld]+query(rd,mid+1,r,lmt-num[ld]);
}
}big,sml; void solve(int id){
LL rest=T-has[p[id].t];
if(rest<0) return;
int l=1,r=n,res;
while(l<=r){
int mid=l+r>>1,lmt=mid>>1;
if(big.num[1]<lmt||sml.num[1]<lmt){ r=mid-1; continue; }
if(big.query(1,1,n,lmt)+sml.query(1,1,n,lmt)>rest) r=mid-1;
else l=mid+1,res=mid;
}
ckmax(ans[res],p[id].w);
} signed main(){
// freopen("treasure.in","r",stdin);
// freopen("treasure.out","w",stdout);
n=read(); T=read(); Q=read();
for(int i=1;i<=n;i++)
p[i].w=read(),has[i]=p[i].t=read(),ans[i]=-1;
sort(p+1,p+n+1); sort(has+1,has+n+1);
ext=unique(has+1,has+n+1)-has-1;
for(int i=1;i<=n;i++)
p[i].t=lower_bound(has+1,has+ext+1,p[i].t)-has;
for(int i=1;i<=n;i++) big.update(1,1,n,p[i].t,1);
for(int i=1;i<=n;i++){
big.update(1,1,n,p[i].t,-1);
solve(i);
sml.update(1,1,n,p[i].t,1);
}
for(int i=n-1;i;i--) ckmax(ans[i],ans[i+1]);
while(Q--){
x=read();
write(ans[x],'\n');
}
return 0;
}

T2 寻找道路

先把只走\(0\)边能到的点缩起来,之后要保证走到的点距离的字典序最小。

\(BFS\),每次取出队列中距离相等的点,先走\(0\)边再走\(1\)边,可以保证队列中距离是单调的。

\(code:\)

T2

#include<bits/stdc++.h>
using namespace std; namespace IO{
typedef long long LL;
int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
void write(int x,char sp){
char ch[20]; int len=0;
if(x<0) x=-x,putchar('-');
do{ ch[len++]=x%10+'0'; x/=10; }while(x);
for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
}
void ckmin(int& x,int y){ x=x<y?x:y; }
void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO; const int NN=1000010,MM=2000010,mod=1e9+7;
int n,m,st,idx,res[NN],head[NN];
int q[NN],l,r;
bool vis[NN];
vector<int>vec;
struct edge{ int to,nex,w; }e[MM];
void add(int a,int b,int c){ e[++idx]=(edge){b,head[a],c}; head[a]=idx; } void dfs(int s){
if(vis[s]) return;
vis[s]=1;
for(int i=head[s],v=e[i].to;i;i=e[i].nex,v=e[i].to)
if(e[i].w) add(st,v,1);
else res[v]=0,dfs(v);
}
void bfs(){
q[l=r=1]=st; res[st]=0;
while(l<=r){
int tmp=res[q[l]];
vec.clear();
while(l<=r&&res[q[l]]==tmp) vec.push_back(q[l++]);
for(int x:vec)
for(int i=head[x],v=e[i].to;i;i=e[i].nex,v=e[i].to)
if(!e[i].w&&res[v]<0){
res[v]=(res[x]<<1)%mod;
q[++r]=v;
}
for(int x:vec)
for(int i=head[x],v=e[i].to;i;i=e[i].nex,v=e[i].to)
if(e[i].w&&res[v]<0){
res[v]=(res[x]<<1)%mod+1;
q[++r]=v;
}
}
} signed main(){
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
n=read(); m=read(); st=n+1;
for(int a,b,c,i=1;i<=m;i++)
a=read(),b=read(),c=read(),add(a,b,c);
memset(res,-1,sizeof(res));
dfs(1); bfs();
for(int i=2;i<=n;i++) write(res[i],' ');
return puts(""),0;
}


T3 猪国杀

最优策略是取小的牌。

令至少拿\(i\)张牌的方案为\(f(i)\),那么\(ans\times A^n=\sum_{i=1}^nf(i)\)。

设\(g_{i,j,k}\)表示有多少个⻓度为\(i\)的正整数序列满足每一个数字不大于\(j\)且所有数字总和不超过\(k\),那么有

\[f(i)=\sum_{j=1}^A\sum_{k=1}^{n-i}g_{i,j-1,m-j\times k}\times\binom{n}{i}\sum_{t\geq k}\binom{n-i}{t}\times(A-j)^{n-i-t}
\]

枚举选的牌中的最大值\(j\),选的最大值个数\(k\)和最大值出现次数\(t\)可得。

考虑如何求\(g\)。可以通过容斥求解。

\[g_{i,j,k}=\sum_{t=0}^i(-1)^t\binom{i}{t}\binom{k-j\times t}{i}
\]

最后一个组合数考虑插板法,将\(k\)有顺序地分为\(i\)个正整数加和的方案数为\(\binom{k-1}{i-1}\),因为要满足强制\(t\)个数大于\(j\)(已固定位置),因此可以看作将\(k-t\times j\)划分为\(i\)个数,最后再在这\(t\)个数上各自加上\(j\),即可保证限制。

另外,因为\(g\)定义为加和不大于\(k\)的序列,因此可以看作将\(k+1\)划分为\(i+1\)个数,多出来的数即为\(i\)个数的和与\(k+1\)的差(至少为\(1\))。

综上,

\[ans\times A^n=\sum_{i=1}^n\sum_{j=1}^A\sum_{k=1}^{n-i}(\sum_{t=0}^i(-1)^t\binom{i}{t}\binom{m-k\times j-t\times(j-1)}{i})\times\binom{n}{i}\sum_{t\geq k}\binom{n-i}{t}(A-j)^{n-i-t}
\]

直接求和即可,复杂度约为\(\Theta(n^2m\log m)\)。

\(code:\)

T3

#include<bits/stdc++.h>
#define int long long
using namespace std; namespace IO{
int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
void write(int x,char sp){
char ch[20]; int len=0;
if(x<0) x=-x,putchar('-');
do{ ch[len++]=x%10+'0'; x/=10; }while(x);
for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
}
void ckmin(int& x,int y){ x=x<y?x:y; }
void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO; const int NN=110,mod=998244353;
int n,m,a;
int ans; namespace Combination{
int fac[NN*10],inv[NN*10];
int C(int x,int y){ return x<0||y<0||x<y?0:fac[x]*inv[y]%mod*inv[x-y]%mod; }
int qpow(int a,int b){
int res=1;
for(;b;b>>=1){
if(b&1) res=res*a%mod;
a=a*a%mod;
}
return res;
}
void init(){
fac[0]=inv[0]=1;
for(int i=1;i<=1000;i++) fac[i]=fac[i-1]*i%mod;
inv[1000]=qpow(fac[1000],mod-2);
for(int i=999;i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
} using namespace Combination; signed main(){
freopen("legend.in","r",stdin);
freopen("legend.out","w",stdout);
n=read(); m=read(); a=read(); init();
for(int i=0;i<=n;i++)
for(int j=1;j<=a;j++)
for(int k=1;k<=n-i&&j*k<=m;k++){
int tmp=0,res=0;
for(int t=0;t<=i;t++)
tmp=(tmp+((t&1)?-1:1)*C(i,t)*C(m-k*j-t*(j-1),i)%mod)%mod;
for(int t=k;t<=n-i;t++)
res=(res+C(n-i,t)*qpow(a-j,n-i-t)%mod)%mod;
ans=(ans+tmp*C(n,i)%mod*res%mod)%mod;
}
ans=ans*qpow(qpow(a,n),mod-2)%mod;
write(ans,'\n');
return 0;
}


T4 数树

可以求出\(T1\)每个联通块中有多少个合法双射,最后除去\(T2\)自己与自己同构的方案。

设\(f_{i,s}\)表示\(i\)的儿子与\(T2\)中的点集\(s\)形成双射的方案数,每次枚举\(T2\)的根,在\(T1\)上做树上背包,最后将所有点作为\(T2\)根的方案累加即可。

说起来挺简单,但确实是神现题。

\(code:\)

T4

#include<bits/stdc++.h>
#define int long long
using namespace std; namespace IO{
int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
void write(int x,char sp){
char ch[20]; int len=0;
if(x<0) x=-x,putchar('-');
do{ ch[len++]=x%10+'0'; x/=10; }while(x);
for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
}
void ckmin(int& x,int y){ x=x<y?x:y; }
void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO; const int NN=3010,mod=998244353;
int n,m,idx,_idx,inv,id[15],head[NN],_head[NN];
int ans,son[15],f[NN][1<<10],g[NN][1<<10];
bool ed[15][15];
int u[15],v[15];
struct edge{ int to,nex; }e[NN<<1],_e[NN<<1];
void add(int a,int b){
e[++idx]=(edge){b,head[a]}; head[a]=idx;
e[++idx]=(edge){a,head[b]}; head[b]=idx;
}
void _add(int a,int b){
_e[++_idx]=(edge){b,_head[a]}; _head[a]=_idx; ed[a][b]=1;
_e[++_idx]=(edge){a,_head[b]}; _head[b]=_idx; ed[b][a]=1;
}
int qpow(int a,int b){
int res=1;
for(;b;b>>=1){
if(b&1) res=res*a%mod;
a=a*a%mod;
}
return res;
}
void _dfs(int s,int fa){
for(int i=_head[s],v=_e[i].to;i;i=_e[i].nex,v=_e[i].to)
if(v!=fa) son[s]|=(1<<v-1),_dfs(v,s);
}
void dfs(int s,int fa){
f[s][0]=1;
for(int i=head[s],v=e[i].to;i;i=e[i].nex,v=e[i].to) if(v!=fa){
dfs(v,s);
for(int j=1;j<=m;j++) if(f[v][son[j]])
for(int k=0;k<(1<<m);k++) if(f[s][k]&&!(k&(1<<j-1)))
(g[s][k|(1<<j-1)]+=f[s][k]*f[v][son[j]])%=mod;
for(int k=1;k<(1<<m);k++) f[s][k]=g[s][k];
}
} signed main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
n=read();
for(int a,b,i=1;i<n;i++)
a=read(),b=read(),add(a,b);
m=read();
for(int i=1;i<m;i++)
u[i]=read(),v[i]=read(),_add(u[i],v[i]);
for(int i=1;i<=m;i++) id[i]=i;
do{
bool flag=1;
for(int i=1;i<m;i++)
if(!ed[id[u[i]]][id[v[i]]]){ flag=0; break; }
inv+=flag;
}while(next_permutation(id+1,id+m+1));
inv=qpow(inv,mod-2);
for(int i=1;i<=m;i++){
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
memset(son,0,sizeof(son));
_dfs(i,0); dfs(1,0);
for(int j=1;j<=n;j++)
(ans+=f[j][son[i]])%=mod;
}
write(ans*inv%mod,'\n');
return 0;
}


2021.10.27考试总结[冲刺NOIP模拟17]的更多相关文章

  1. 2021.10.26考试总结[冲刺NOIP模拟16]

    T1 树上的数 \(DFS\)一遍.结构体存边好像更快? \(code:\) T1 #include<bits/stdc++.h> using namespace std; namespa ...

  2. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  3. NOIP模拟 17.8.15

    NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  4. NOIP模拟 17.8.20

    NOIP模拟17.8.20 A.阶乘[题目描述]亲爱的xyx同学正在研究数学与阶乘的关系,但是他喜欢颓废,于是他就制作了一个和阶乘有关系的数学游戏:给出两个整数 n,m,令 t = !n,每轮游戏的流 ...

  5. NOIP模拟 17.8.18

    NOIP模拟17.8.18 A.小菜一碟的背包[题目描述]Blice和阿强巴是好朋友但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习阿强巴有 n头奶牛,每头奶牛每天可以产一定量的奶,同时也 ...

  6. NOIP模拟 17.8.16

    NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  7. NOIP模拟 17.8.14

    NOIP模拟17.8.14 (天宇哥哥考察细心程度的题) [样例解释]如果删去第一个 1:在[3,1,2]中有 3 个不同的数如果删去 3:在[1,1,2]中有 2 个不同的数如果删去第二个 1:在[ ...

  8. NOIP模拟17.9.21

    NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...

  9. NOIP模拟 17.8.17

    NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...

随机推荐

  1. Spring基于XML方式加载Bean定义信息(又名:Spring IOC源码时序图)-图解

  2. MySQL查询之内连接,外连接查询场景的区别与不同

    前言 我在写sql查询的时候,用的最多的就是where条件查询,这种查询也叫内连查询inner join,当然还有外连查询outer join,左外连接,右外连接查询,常用在多对多关系中,那他们区别和 ...

  3. vue-cookies使用

    一.安装 vue-cookies npm install vue-cookies --save 二.引入并声明使用 import Vue form 'Vue' import VueCookies fr ...

  4. Java数学函数的使用

    Java的Math类中提供了一系列关于数学运算的静态方法,常见的运算整理如下[1] 算数运算 Math.sqrt() // 平方根 Math.cbrt() // 立方根 Math.pow(a, b) ...

  5. Nginx禁止ip方式访问80、443端口

    在nginx.conf配置文件中 include /etc/nginx/conf.d/*.conf; 之前加入以下内容 server { listen 80 default; listen 443 d ...

  6. CF444C-DZY Loves Colors【线段树,set】

    正题 题目链接:https://www.luogu.com.cn/problem/CF444C 题目大意 \(n\)个物品第\(i\)个颜色为\(i\),权值为\(0\).要求支持\(m\)次操作 给 ...

  7. 基于Processing图像序列处理保存导出的流程梳理

    做一个基于processing的图像序列处理保存导出的流程梳理.本案例没有什么实质性的目的,仅为流程梳理做演示. 准备 把需要处理的影像渲染成序列图片,可以在PR中剪辑并导出PNG序列[格式倒是没什么 ...

  8. maven插件maven-install-plugin

    maven-install-plugin负责将获取的jar包安装到本地仓库 <build> <plugin> <groupId>org.apache.maven.p ...

  9. RabbitMQ 3.9.7 镜像模式集群与Springboot 2.5.5 整合

    1. 概述 老话说的好:做人要懂得变通,善于思考,有时稍微转个弯,也许问题就解决了. 言归正传,之前我们聊了 RabbitMQ 3.9.7 镜像模式集群的搭建,今天我们来聊聊 RabbitMQ 3.9 ...

  10. Skywalking-13:Skywalking模块加载机制

    模块加载机制 基本概述 Module 是 Skywalking 在 OAP 提供的一种管理功能特性的机制.通过 Module 机制,可以方便的定义模块,并且可以提供多种实现,在配置文件中任意选择实现. ...