NOIP模拟84(多校17)
T1 宝藏
解题思路
考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了??
考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的做法指针好像并不满足单调性。。
口胡一下正解,做法差不多,只不过枚举的方式改变了,但是都需要先对于 w 进行排序,枚举每一种长度的序列,单调指针维护最大的合法的值。
这个是有单调性的,然后主席树或者权值线段树维护均可。
code
其实是假做法
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=3e5+10,M=1e6+10;
int n,m,q,lim,ans[N];
struct Node{int w,t;}s[N];
struct Segment_Tree
{
int root,all;
struct node{int siz,dat;}tre[M<<2];
#define push_up(x) tre[x].dat=tre[ls].dat+tre[rs].dat,tre[x].siz=tre[ls].siz+tre[rs].siz
void insert(int x,int l,int r,int pos,int val)
{
if(l==r) return tre[x].siz+=val,tre[x].dat+=val*pos,void();
int mid=(l+r)>>1;
if(pos<=mid) insert(ls,l,mid,pos,val);
else insert(rs,mid+1,r,pos,val);
push_up(x);
}
int query(int x,int l,int r,int k)
{
if(!tre[x].siz||!k) return 0;
if(l==r) return tre[x].dat*k/tre[x].siz;
int mid=(l+r)>>1;
if(tre[ls].siz>k) return query(ls,l,mid,k);
return tre[ls].dat+query(rs,mid+1,r,k-tre[ls].siz);
}
}T1,T2;
bool comp(Node x,Node y){return x.w<y.w;};
#undef int
int main()
{
#define int long long
freopen("treasure.in","r",stdin); freopen("treasure.out","w",stdout);
n=read(); m=read(); q=read(); memset(ans,-1,sizeof(ans));
for(int i=1;i<=n;i++) s[i].w=read(),s[i].t=read(),lim=max(lim,s[i].t);
sort(s+1,s+n+1,comp); for(int i=1;i<=n;i++) T2.insert(1,0,lim,s[i].t,1);
for(int i=1,val=0;i<=n;i++)
{
T2.insert(1,0,lim,s[i].t,-1); val=min(val,min(i-1,n-i));
while(val<min(i-1,n-i)&&T1.query(1,1,lim,val+1)+T2.query(1,1,lim,val+1)+s[i].t<=m) val++;
while(val>0&&T1.query(1,1,lim,val)+T2.query(1,1,lim,val)+s[i].t>m) val--;
ans[val]=max(ans[val],s[i].w); T1.insert(1,0,lim,s[i].t,1);
}
for(int i=n/2;i>=0;i--) ans[i]=max(ans[i],ans[i+1]);
while(q--){int x;x=read();printf("%lld\n",ans[min(n,x/2)]);}
return 0;
}
T2 寻找道路
解题思路
首先考虑去除前导 0 的影响,直接搜索一遍查找所有到 1 节点距离为 0 的点记录下来就好了。
剩下的部分就是字典序以及长度的问题了,那么长度的问题直接 BFS 就可以了。
字典序大小的话,对于队列中长度一致并且数字序列相同的一起拿出来,然后优先扫 0 边权的边再扫 1 边权的边。
标记一下,保证每个节点只访问一次。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10,mod=1e9+7,INF=1e18;
int n,m,top,sta[N],len[N],dis[N];
int tot=1,head[N],ver[N<<1],nxt[N<<1],edge[N<<1];
vector<int> dis0;
queue<int> q;
bool vis[N];
void add_edge(int x,int y,int val)
{
ver[++tot]=y; edge[tot]=val;
nxt[tot]=head[x]; head[x]=tot;
}
#undef int
int main()
{
#define int long long
freopen("path.in","r",stdin); freopen("path.out","w",stdout);
n=read(); m=read(); memset(len,0x3f,sizeof(len)); dis[1]=len[1]=0;
for(int i=1,x,y,z;i<=m;i++) x=read(),y=read(),z=read(),add_edge(x,y,z);
q.push(1); dis0.push_back(1);
while(!q.empty())
{
int x=q.front(); q.pop();
for(int i=head[x];i;i=nxt[i])
if(!vis[ver[i]]&&!edge[i])
vis[ver[i]]=true,dis0.push_back(ver[i]),q.push(ver[i]);
}
for(auto it:dis0) q.push(it),dis[it]=len[it]=0;
while(!q.empty())
{
top=0; sta[++top]=q.front(); q.pop();
while(!q.empty()&&len[q.front()]==len[sta[1]]&&dis[q.front()]==dis[sta[1]])
sta[++top]=q.front(),q.pop();
for(int i=1;i<=top;i++)
{
int x=sta[i];
for(int j=head[x];j;j=nxt[j])
{
int to=ver[j],val=edge[j];
if(val||vis[to]||len[to]<=len[x]+1) continue;
len[to]=len[x]+1; dis[to]=dis[x]*2%mod;
vis[to]=true; q.push(to);
}
}
for(int i=1;i<=top;i++)
{
int x=sta[i];
for(int j=head[x];j;j=nxt[j])
{
int to=ver[j],val=edge[j];
if(!val||vis[to]||len[to]<=len[x]+1) continue;
len[to]=len[x]+1; dis[to]=(dis[x]*2+1)%mod;
vis[to]=true; q.push(to);
}
}
}
for(int i=2;i<=n;i++) printf("%lld ",len[i]>=INF?-1ll:dis[i]);
return 0;
}
T3 猪国杀
解题思路
其实是个假期望,计数 DP 。
我们只需要知道每一种方案的总和了,最后乘上一个 \(A^n\) 。
设 \(g_{i,j,k}\) 表示有 多少个⻓度为 \(i\) 的正整数序列满足每一个数字不大于 \(j\) 且所有数字总和不超过 \(k\) 。
假设我们能够求出来这个值,考虑如何计算答案。
枚举选的牌中的最大值 \(j\) ,最大值个数 \(k\) ,以及选了 \(i\) 个小于 \(j\) 的牌,于是就有了:
\]
对于计算过方案数的两个序列就可以视为序列中的元素是等价的了,也就是再乘上一个可重集排列。
因为我们要选择 \(k\) 个 \(j\) 但是序列中不一定只有 \(k\) 个 \(j\) 因此我们需要让前面的牌的总和是 \(m-j\times k\) 然后枚举后面有多少个 \(j\) 同时计算剩下的取值的个数。
对于 \(g_{i,j,k}\) 可以通过枚举多少个大于 \(j\) 的数字进行计算,可以运用挡板法,由于挡板之间 1 的个数可能会超过 \(j\) 因此需要容斥一下:
\]
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=110,M=1010,mod=998244353;
int n,m,lim,mx,ans,fac[M],ifac[M];
void add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
int power(int x,int y,int p=mod)
{
int temp=1;
while(y)
{
if(y&1) temp=temp*x%p;
x=x*x%p; y>>=1;
}
return temp;
}
int C(int x,int y){return x<y?0:fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
int g(int i,int j,int k)
{
int sum=0;
for(int p=0,sym=1;p<=i;p++,sym=-sym)
{
int temp=C(i,p)*C(k-p*j,i)%mod;
if(temp) add(sum,sym*temp+((~sym)?0:mod));
else break;
}
return sum;
}
#undef int
int main()
{
#define int long long
freopen("legend.in","r",stdin); freopen("legend.out","w",stdout);
n=read(); m=read(); lim=read(); mx=max(n,max(m,lim));
fac[0]=ifac[0]=1; for(int i=1;i<=mx;i++) fac[i]=fac[i-1]*i%mod;
ifac[mx]=power(fac[mx],mod-2); for(int i=mx-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
for(int i=0;i<=n;i++)
for(int j=1;j<=lim;j++)
for(int k=1;k<=n-i;k++)
{
int base=0,temp=C(n,i)%mod*g(i,j-1,m-j*k)%mod;
if(!temp) continue;
for(int p=k;p<=n-i;p++)
{
int temp=C(n-i,p); if(!temp) break;
add(base,temp*power(lim-j,n-i-p)%mod);
}
if(base) add(ans,base*temp%mod);
}
printf("%lld",ans*power(power(lim,n),mod-2)%mod); return 0;
}
T4 数树
解题思路
枚举以哪个节点为根以及子树和 T2 的匹配程度来判断。
具体实现可以 Hash+素数 防止重复。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=3e3+10,M=20,bas=23,mod=998244353;
int n,m,cnt,ans,pri[N],siz[N];
int tot=1,head[N],ver[N<<1],nxt[N<<1];
ull has[N];
unordered_map<ull,int> ys,f[N];
unordered_map<ull,bool> can,mp;
vector<int> v[M];
bitset<N> vis;
void add_edge(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void Get_Prime()
{
for(int i=2;i<=1000;i++)
{
if(!vis[i]) pri[++cnt]=i;
for(int j=1;j<=cnt&&pri[j]*i<=1000;j++)
{
vis[i*pri[j]]=true;
if(i%pri[j]==0) break;
}
}
}
void pre_dfs(int x,int fa)
{
siz[x]=has[x]=1;
for(auto to:v[x])
{
if(to==fa) continue;
pre_dfs(to,x); siz[x]+=siz[to];
has[x]+=has[to]*pri[siz[to]+bas];
}
mp.insert(make_pair(has[x],true));
ys.insert(make_pair(has[x],siz[x]+bas));
}
void dfs(int x,int fa)
{
f[x].insert(make_pair(1,1));
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i]; if(to==fa) continue;
unordered_map<ull,int> temp=f[x]; dfs(to,x);
for(auto it1:temp) for(auto it2:f[to])
{
ull rec=it1.first+it2.first*pri[ys.find(it2.first)->second];
f[x][rec]=(f[x][rec]+it1.second*it2.second)%mod;
}
}
vector<ull> dela;
for(auto it:f[x]) if(mp.find(it.first)==mp.end()) dela.push_back(it.first);
for(auto it:dela) f[x].erase(it);
}
#undef int
int main()
{
#define int long long
freopen("count.in","r",stdin); freopen("count.out","w",stdout);
n=read(); Get_Prime();
for(int i=1,x,y;i<n;i++)
x=read(),y=read(),
add_edge(x,y),add_edge(y,x);
m=read();
for(int i=1,x,y;i<m;i++)
x=read(),y=read(),
v[x].push_back(y),v[y].push_back(x);
for(int i=1;i<=m;i++) pre_dfs(i,0),can.insert(make_pair(has[i],true));
dfs(1,0);
for(auto it:can)
for(int i=1;i<=n;i++)
if(f[i].find(it.first)!=f[i].end())
ans=(ans+f[i].find(it.first)->second)%mod;
printf("%lld",ans);
return 0;
}
NOIP模拟84(多校17)的更多相关文章
- NOIP模拟83(多校16)
前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...
- Noip模拟79 2021.10.17(题目名字一样)
T1 F 缩点缩成个$DAG$,然后根据每个点的度数计算期望值 1 #include<cstdio> 2 #include<cstring> 3 #include<vec ...
- Noip模拟18 2021.7.17 (文化课专场)
T1 导弹袭击(数学) 显然,我们要找到最优的A,B使得一组a,b优于其他组那么可以列出: $\frac{A}{a_i}+\frac{B}{b_i}<\frac{A}{a_j}+\frac{B} ...
- Noip模拟55 2021.9.17(打表大胜利)
T1 skip 普通$dp$很好打: $f[i]=max(f[j]-\sum_{k=1}^{K}k+a_i)$ 就是要注意边界问题很烦人. 1 #include<bits/stdc++.h> ...
- Noip模拟42 2021.8.17
T1 卷 一看跟没有上司的舞会一样,直接敲了然后试个自己造的样例对了就跑了... 然而把它想简单了,乘积取模,还能比大小吗????? 显然不能 所以直接让对数的加和跟着$dp$直接一起跑,比大小的都用 ...
- Noip模拟8 2021.6.17
T1 星际旅行 仔细一看,发现像一个欧拉路(简称一笔画). 满足"可以一笔画"的条件是: 1.所有点都有偶数条连边; 2.有偶数个点连奇数条边; 满足以上两个条件的任意一个即可一笔 ...
- NOIP模拟92(多校25)
前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...
- Noip模拟84 2021.10.27
以后估计都是用\(markdown\)来写了,可能风格会有变化 T1 宝藏 这两天老是会的题打不对,还是要细心... 考场上打的是维护\(set\)的做法,但是是最后才想出来的,没有维护对于是没有交. ...
- NOIP模拟85(多校18)
前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...
随机推荐
- MapReduce 示例:减少 Hadoop MapReduce 中的侧连接
摘要:在排序和reducer 阶段,reduce 侧连接过程会产生巨大的网络I/O 流量,在这个阶段,相同键的值被聚集在一起. 本文分享自华为云社区<MapReduce 示例:减少 Hadoop ...
- Jmeter系列(10)- Linux环境安装之Jmeter下载配置
step-1下载 我是之前windows有,就直接copy到Linux系统了 step-2Jmter放到local目录 mv apache-jmeter-5.2.1 /usr/local/ step- ...
- Writing in the Science 01
INTRODUCTION What makes good writing? Good writing communicates an idea clearly and effectively. Goo ...
- eps出坑出坑
1 visio格式转eps 先将Visio保存为pdf格式文件 使用adobe acrobat编辑pdf 先将文件裁剪至所需大小 随后点编辑,选择全选,然后文件,导出到,内嵌postscript 2 ...
- HTML 网页开发、CSS 基础语法—— 一. HTML概述(了解网页)
1. 网页的本质 ① HTML就是用来制作网页文件的. ② 浏览器查看的网页都是.html或.htm文件. ③ HTML叫做超文本标记语言(Hypertext Markup Language),用于搭 ...
- 学会了这些英文单词,妈妈再也不用担心我学不会Python
前言 很多转行或刚入行做测试的小伙伴学习Python时,经常会问一句话:我英语不好能不能学会代码. 答案是:肯定的!你如果英语好学开发语言肯定要比不会英语的小伙伴学起来.当代码报错时全是英文,毕竟 ...
- BATJ经典软件测试面试题我连答案都告诉你了,如果你不想月薪上万,那你别看!
单项选择题:共20小题,每小题1 分,满分20分:请将答案填入题后括号中. 1. 在软件生命周期的哪一个阶段,软件缺陷修复费用最低(A) A.需求分析(编制产品说明书) B.设计 C.编码 ...
- 【C++ Primer Plus】编程练习答案——第7章
1 double ch7_1_harmonicaverage(double a, double b) { 2 return 2 / (1 / a + 1 / b); 3 } 4 5 void ch7_ ...
- heoi2020信号传递
状压dp 我状压学得是真烂..... 考试的时候想了状压,可是一直都是在枚举位置,没有神魔实质性突破.其实这道题的关键瓶颈也在于此,状压压的是号,而不是位置.如果 $i<=j$ 那么贡献为 $j ...
- Python:PNG图像生成MP4
Python:PNG图像生成MP4 需求 需要将多张*.PNG图像,生成mp4格式的视频文件. 实现 利用Python中image库生成*.gif格式图像,但是图片未经压缩,文件体量较大. movie ...