2017.8.2 Noip2018模拟测试赛(十八)
日期: |
八月二日 |
总分: |
300分 |
难度: |
提高 ~ 省选 |
得分: |
40分(又炸蛋了!!) |
题目列表:
T1:分手是祝愿
T2:残缺的字符串
T3:树点涂色
赛后心得:
哎,T1求期望,放弃。
看T2像是 KMP 打完发现并不可做,有感觉像是 FFT,放弃
T3我打了个树剖套线段树,调了好久,发现修改操作处理不了,又想到 LCT……
比赛结束!!…… MMP
题解:
T1:分手是祝愿
期望dp,首先,最优解肯定是从大到小,有开的灯就把它按灭
(因为不按的话,编号小的不会对大的有影响,所以会导致这盏灯一直亮着)
不考虑 k,f[i] 表示最优 i 步按得次数的期望。
有 i 种情况能按到对的按钮,n-i 种按错,则状态转移方程:
$$ f_i=\frac{i}{n}+\frac{n-i}{n}(1+f_i+f_{i+1}) $$
(n个开关,i个正确,其他n-i个会增加一个错误,需f[n+1]+f[n]次操作变到i-1)
化简得:
$$ f_i=\frac{n+(n-i)f_{i+1}}{i} $$
显然 f[n]=1,k 以下也为1,直接递推求解。
最后 $ans=\sum_{i=1}^n f_i$
CODE:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std; #define mod 100003LL
int n,k,cnt,ans,fac,inv[];
int g[],f[];
bool vis[];
vector<int> fc[]; int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)scanf("%d",vis+i);
fac=inv[]=inv[]=;
for(int i=;i<=n;i++){
inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
fac=1LL*fac*i%mod;
}
for(int i=;i<=n;i++)
for(int j=i;j<=n;j+=i)fc[j].push_back(i);
for(int i=n;i>=;i--)
if(vis[i]){
for(int j=;j<fc[i].size();j++)
vis[fc[i][j]]^=;
cnt++;
}
if(cnt<=k){
printf("%d\n",1LL*cnt*fac%mod);
return ;
}
g[n]=;
for(int i=;i<=k;i++)g[i]=;
for(int i=n-;i>k;i--)g[i]=(1LL*(n-i)*g[i+]%mod+n)*inv[i]%mod;
for(int i=cnt;i>=;i--)(ans+=g[i])%=mod;
printf("%d\n",1LL*ans*fac%mod);
}
T2:残缺的字符串
看起来像是KMP,实际上是FFT。
题解戳这里,我认为他讲的已经很清楚了!
CODE:
#include<iostream>
#include<cstdio>
#include<complex>
using namespace std; const double PI=acos(-);
typedef complex<long double> cmplx;
int n,m,bit=,rev[],ans[];
cmplx a[],b[];
char A[],B[]; void get_rev(){
while(bit<=n+m)bit<<=;
for(int i=;i<bit;i++)
rev[i]=(rev[i>>]>>)|(i&)*(bit>>);
} void FFT(cmplx a[],int dft){
for(int i=;i<bit;i++)
if(i<rev[i])swap(a[i],a[rev[i]]);
for(int i=;i<bit;i<<=){
cmplx W=exp(cmplx(,dft*PI/i));
for(int j=;j<bit;j+=i<<){
cmplx w(,);
for(int k=j;k<i+j;k++,w*=W){
cmplx x=a[k];
cmplx y=w*a[k+i];
a[k]=x+y,a[k+i]=x-y;
}
}
}
if(dft==-)for(int i=;i<bit;i++)a[i]/=bit;
} int main(){
scanf("%d%d",&m,&n);
scanf("%s%s",A,B);
for(int i=;i<m;i++)
if(A[i]!='*')a[m-i-]=(long double)1.0/(A[i]-'a'++1e3);
for(int i=;i<n;i++)
if(B[i]!='*')b[i]=(long double)B[i]-'a'++1e3;
get_rev();
FFT(a,),FFT(b,);
for(int i=;i<bit;i++)a[i]*=b[i];
FFT(a,-);
for(int i=m-;i<=n-;i++){
int x=a[i].real()+0.25;
if(fabs(a[i].real()-x)<1e-){
ans[++ans[]]=i-m+;
}
}
printf("%d\n",ans[]);
for(int i=;i<=ans[];i++)
printf("%d ",ans[i]);
}
其实这种解法像 Hash 一样有几率发生碰撞的,可能小数加小数,变为整数,但如同 Hash 正确率够高,不用担心。
卡精度啊!!我用了 long double 慢的像屎一样MMP
T3:树点涂色
LCT+线段树
CODE:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; #define lch ch[0]
#define rch ch[1]
int n,m,opt,x,y,cnt,tot=,h[];
int dep[],siz[],son[];
int tid[],rak[],tp[],fa[];
int maxv[],add[];
struct Edge{
int x,next;
}e[];
struct Splay{
int fa,ch[];
}v[]; inline void add_edge(int x,int y){
e[++tot].x=y;
e[tot].next=h[x],h[x]=tot;
} void dfs1(int x,int father,int deep){
siz[x]=,fa[x]=father,dep[x]=deep;
v[x].fa=father;
for(int i=h[x];i;i=e[i].next){
if(e[i].x==father)continue;
dfs1(e[i].x,x,deep+);
siz[x]+=siz[e[i].x];
if(siz[e[i].x]>siz[son[x]])son[x]=e[i].x;
}
} void dfs2(int x,int top){
tid[x]=++cnt,rak[cnt]=x,tp[x]=top;
if(son[x])dfs2(son[x],top);
for(int i=h[x];i;i=e[i].next){
if(e[i].x==fa[x]||e[i].x==son[x])continue;
dfs2(e[i].x,e[i].x);
}
} void pushdown(int o){
add[o<<]+=add[o];
add[o<<|]+=add[o];
maxv[o<<]+=add[o];
maxv[o<<|]+=add[o];
add[o]=;
} void build(int o,int l,int r){
if(r-l==){
maxv[o]=dep[rak[l]]+;
}else{
int mid=l+r>>;
build(o<<,l,mid),build(o<<|,mid,r);
maxv[o]=max(maxv[o<<],maxv[o<<|]);
}
} void update(int o,int l,int r,int x,int y,int a){
if(l>=x&&r<=y){
add[o]+=a,maxv[o]+=a;
}else{
pushdown(o);
int mid=l+r>>;
if(x<mid)update(o<<,l,mid,x,y,a);
if(y>mid)update(o<<|,mid,r,x,y,a);
maxv[o]=max(maxv[o<<],maxv[o<<|]);
}
} int query(int o,int l,int r,int x,int y){
if(l>=x&&r<=y)return maxv[o];
pushdown(o);
int mid=l+r>>;
int ans=;
if(x<mid)ans=max(ans,query(o<<,l,mid,x,y));
if(y>mid)ans=max(ans,query(o<<|,mid,r,x,y));
return ans;
} int LCA(int x,int y){
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]])swap(x,y);
x=fa[tp[x]];
}
if(dep[x]>dep[y])swap(x,y);
return x;
} inline bool isroot(int x){
return v[v[x].fa].lch!=x&&v[v[x].fa].rch!=x;
} inline void rotate(int x){
int y=v[x].fa,z=v[y].fa;
if(!isroot(y))v[z].ch[v[z].rch==y]=x;
v[x].fa=z;
bool k=v[y].rch==x;
v[y].ch[k]=v[x].ch[k^];
if(v[x].ch[k^])v[v[x].ch[k^]].fa=y;
v[x].ch[k^]=y,v[y].fa=x;
} inline void splay(int x){
while(!isroot(x)){
int y=v[x].fa,z=v[y].fa;
if(!isroot(y)){
if(v[y].lch==x^v[z].lch==y)rotate(x);
else rotate(y);
}
rotate(x);
}
} void access(int x){
for(int y=;x;y=x,x=v[x].fa){
splay(x);
if(v[x].rch){
int k=v[x].rch;
while(v[k].lch)k=v[k].lch;
update(,,n+,tid[k],tid[k]+siz[k],);
}
v[x].rch=y;
if(y){
int k=y;
while(v[k].lch)k=v[k].lch;
update(,,n+,tid[k],tid[k]+siz[k],-);
}
}
} int main(){
// puts("silly pcj!!!")
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
dfs1(,,),dfs2(,);
build(,,n+);
for(int i=;i<=m;i++){
scanf("%d",&opt);
if(opt!=)scanf("%d",&x);
else scanf("%d%d",&x,&y);
if(opt==)access(x);
if(opt==){
int lca=LCA(x,y);
int sum1=query(,,n+,tid[x],tid[x]+);
int sum2=query(,,n+,tid[y],tid[y]+);
int sum=query(,,n+,tid[lca],tid[lca]+);
printf("%d\n",sum1+sum2-*sum+);
}
if(opt==)
printf("%d\n",query(,,n+,tid[x],tid[x]+siz[x]));
}
}
2017.8.2 Noip2018模拟测试赛(十八)的更多相关文章
- 2017.8.1 Noip2018模拟测试赛(十七)
日期: 八月第一天 总分: 300分 难度: 提高 ~ 省选 得分: 100分(不应该啊!) 题目目录: T1:战争调度 T2:选数 T3:由乃的OJ 赛后心得: MMP,首先第一题花了大概 ...
- 2018.7.31 Noip2018模拟测试赛(十六)
日期: 七月最后一天 总分: 300分 难度: 提高 ~ 省选 得分: 30分(少的可怜) 我太弱了:(题目目录) T1:Mushroom追妹纸 T2:抵制克苏恩 T3:美味 失分分析:(QA ...
- 2018.8.7 Noip2018模拟测试赛(二十)
日期: 八月七号 总分: 300分 难度: 提高 ~ 省选 得分: 100分(呵呵一笑) 题目列表: T1:SS T2:Tree Game T3:二元运算 赛后反思: Emmmmmm…… 开 ...
- 2018.8.6 Noip2018模拟测试赛(十九)
日期: 八月六号 总分: 300分 难度: 提高 ~ 省选 得分: 10分(MMP) 题目目录: T1:Tree T2:异或运算 T3:Tree Restoring 赛后反思: Emmmmm ...
- 2018.8.8 Noip2018模拟测试赛(二十一)
日期: 八月七号 总分: 300分 难度: 提高 ~ 省选 得分: 112分(OvO) 题目目录: T1:幸福的道路 T2:Solitaire T3:Flags 赛后心得: 第一题裸树d啊! ...
- [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania
[2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...
- noi2019模拟测试赛(四十七)
noi2019模拟测试赛(四十七) T1与运算(and) 题意: 给你一个序列\(a_i\),定义\(f_i=a_1\&a_2\&\cdots\&a_i\),求这个序列的所 ...
- [CSP-S模拟测试]:赛(贪心+三分)
题目描述 由于出题人思维枯竭所以想不出好玩的背景.有$n$个物品,第$i$个物品的价格是$v_i$,有两个人,每个人都喜欢$n$个物品中的一些物品.要求选出正好$m$个物品,满足选出的物品中至少有$k ...
- 【2016北京集训测试赛(八)】 crash的数列 (思考题)
Description 题解 题目说这是一个具有神奇特性的数列!这句话是非常有用的因为我们发现,如果套着这个数列的定义再从原数列引出一个新数列,它居然还是一样的...... 于是我们就想到了能不能用多 ...
随机推荐
- Python re module (regular expressions)
regular expressions (RE) 简介 re模块是python中处理正在表达式的一个模块 r"""Support for regular expressi ...
- 性能优化之MySQL优化(慕课)
MySQL数据库优化 1-1MySQL优化简介 数据库优化的目的 避免出现页面访问错误 由于数据库连接timeout产生5XX错误 由于慢查询造成页面无法加载 由于阻塞造成数据无法提交 增加数据库的稳 ...
- React组件自适应窗口宽高
很多时候我们需要组件能够根据窗口变化改变宽高,有时候可以使用css,有时候需要随数据调整则使用js计算. 比如说,当我们在页面中放置一个iframe时,我们希望它的宽高随着其父元素or窗口的变化而变化 ...
- Linux下如何通过命令检查网卡是否插上网线
How To:Linux下如何通过命令检查网卡是否插上网线 主要工具为ethtool来检查,主要关注的字段为"Link detected",注意如下的输出,其中em4实际物理上 ...
- Windows 10 建立wifi热点
如果当前是台式机那么需要一个usb的无线网卡,这里要注意如果你是使用台式机并且通过有线的方式上网,但是你的无线网卡适配器不能在禁用状态. 这里首先打开[运行]输入cmd,打开cmd(注意,这里要使用管 ...
- Docker系列一:Docker的介绍和安装
Docker介绍 Docker是指容器化技术,用于支持创建和实验Linux Container.借助Docker,你可以将容器当做重量轻.模块化的虚拟机来使用,同时,你还将获得高度的灵活性,从而实现对 ...
- SpringMVC 项目中引用其他 Module 中的方法
1. 将要引用的Module 引入项目中 2. 在主Module中添加依赖, 3. 被引用的类必须放在 Module 中/src/下的某个package中,否则引用不到(重要)
- 使用jmeter做简单的压测(检查点、负载设置、聚合报告)
1.添加断言(检查点) 在需要压测的接口下添加--断言--响应断言,取接口响应中包含有的数据即可 检查点HTTP请求-->断言-->响应断言1.名称.注释2.Apply to//作用于哪里 ...
- ultraedit编辑器破解版下载
ultraedit一款功能丰富的网站建设软件,需要的朋友可以看看. 百度百科:UltraEdit 是一套功能强大的文本编辑器,可以编辑文本.十六进制.ASCII 码,完全可以取代记事本(如果电脑配置足 ...
- python并发编程之线程(创建线程,锁(死锁现象,递归锁),GIL锁)
什么是线程 进程:资源分配单位 线程:cpu执行单位(实体),每一个py文件中就是一个进程,一个进程中至少有一个线程 线程的两种创建方式: 一 from threading import Thread ...