日期:

八月第一天

 总分:

300分

 难度:

提高 ~ 省选  

 得分:

100分(不应该啊!)

题目目录:

T1:战争调度

T2:选数

T3:由乃的OJ

赛后心得:

MMP,首先第一题花了大概一半的时间,碰巧想到了正解。

好吧,作为数学渣的我看到T2肯定是懵的啦!T3又那么难,导致我后半场比赛都在发呆……

看来我要恶补数学了!!……

题解:

T1:战争调度

树形dp,暴力枚举每个点的染色情况,发$f[i][j]$表示$i$的子树中,有$j$个黑点,所产生的最大贡献。

时间复杂度 $O(2^{2n+1})$

CODE:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; int n,m,ans=,f[][],v[][][];
bool p[]; void dfs(int x,int d){
memset(f[x],,sizeof(f[x]));
if(d==){
for(int j=;j<=n-;j++){
if(p[j+])f[x][]+=v[x][j][];
else f[x][]+=v[x][j][];
}
return;
}
p[d]=true,dfs(x<<,d-),dfs(x<<|,d-);
for(int i=;i<(<<d-);i++){
for(int j=;j<(<<d-);j++)
f[x][i+j]=max(f[x][i+j],f[x<<][i]+f[x<<|][j]);
}
p[d]=false,dfs(x<<,d-),dfs(x<<|,d-);
for(int i=;i<(<<d-);i++){
for(int j=;j<(<<d-);j++)
f[x][i+j]=max(f[x][i+j],f[x<<][i]+f[x<<|][j]);
}
} int main(){
scanf("%d%d",&n,&m);
for(int i=(<<n-);i<(<<n);i++){
for(int j=;j<=n-;j++)
scanf("%d",v[i][j]+);
}
for(int i=(<<n-);i<(<<n);i++){
for(int j=;j<=n-;j++)
scanf("%d",v[i][j]+);
}
dfs(,n);
for(int i=;i<=m;i++)ans=max(ans,f[][i]);
printf("%d",ans);
}

T2:选数

推公式应该不算太难,只不过这题要用杜教筛。

\begin{aligned}
ans&=\sum^H_{x_i=L}[gcd(x_i)=K]\\
&=\sum^h_{x_i=l}[gcd(x_i)=1] &(l=\lfloor\frac{L-1}{K}\rfloor,h=\lfloor\frac{H}{K}\rfloor)\\
&=\sum^h_{x_i=l}\sum_{d\mid gcd(x_i)}\mu(d)\\
&=\sum^h_{x_i=l}\sum_{d\mid x_i}\mu(d)\\
&=\sum^h_{d=1}\sum_{l<x_i h,d\mid x_i}\mu(d)\\
&=\sum^h_{d=1}(\lfloor\frac{h}{d}\rfloor-\lfloor\frac{l}{d}\rfloor)^n\mu(d)\\
\end{aligned}

CODE:

 #include<iostream>
#include<cstdio>
#include<map>
using namespace std; #define mod 1000000007
int n,k,l,r,ans=;
int mu1[],pri[],cnt=;
bool vis[];
map<int,int> mu2; int qpow(int x,int y){
int ans=;
while(y){
if(y&)ans=1LL*ans*x%mod;
y>>=,x=1LL*x*x%mod;
}
return ans;
} int init(){
mu1[]=;
for(int i=;i<=;i++){
if(!vis[i]){
mu1[i]=-;
pri[++cnt]=i;
}
for(int j=;j<=cnt&&i*pri[j]<=;j++){
vis[i*pri[j]]=true;
if(i%pri[j]==){
mu1[i*pri[j]]=;break;
}else mu1[i*pri[j]]=-mu1[i];
}
}
for(int i=;i<=;i++)mu1[i]+=mu1[i-];
} int get_mu(int x){
if(x<=)return mu1[x];
if(mu2.count(x))return mu2[x];
long long ans=;
for(int i=,pos;i<=(x>>);i=pos+){
pos=x/(x/i);
ans-=1LL*(get_mu(pos)-get_mu(i-))*(x/i-);
}
return mu2[x]=(ans+mod)%mod;
} int main(){
scanf("%d%d%d%d",&n,&k,&l,&r);
init();
l=(l-)/k,r=r/k;
for(int i=,pos;i<=r;i=pos+){
pos=min(r/(r/i),l/i?(l/(l/i)):(int)2e9);
ans=(ans+1LL*qpow(r/i-l/i,n)*(get_mu(pos)-get_mu(i-)))%mod;
}
printf("%d",(ans+mod)%mod);
}

T3:由乃的OJ

强烈建议先做简化版——起床困难综合症

核心:位运算每位独立,互不影响,不像加法、乘法会有进位!!

这个只不过变为了多组查询,树上操作。

用树剖啊!!线段树维护每一位正着和反着,每一位 1 与 0 的情况,压在一个 unsigned long long 里

会做那题,肯定能想到这题的正解,只不过很考验代码实现能力。

CODE:

 #include<iostream>
#include<cstdio>
using namespace std; #define LL long long
#define lch (o<<1)
#define rch (o<<1|1)
int n,m,k,ot,x,y,tot=,cnt=,h[];
int fa[],dep[],son[],opt[];
int siz[],tp[],tid[],rak[];
unsigned long long z,val[];
struct Node{
unsigned long long L0,L1,R0,R1;
}v[],ans1[],ans2[];
struct Edge{
int x,next;
}e[]; 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){
fa[x]=father,dep[x]=deep,siz[x]=;
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){
tp[x]=top,tid[x]=++cnt,rak[cnt]=x;
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);
}
} unsigned LL opr(unsigned LL x,int opt,unsigned LL y){
if(opt==)return x&y;
if(opt==)return x|y;
if(opt==)return x^y;
} Node merge(Node l,Node r){
Node o;
o.L0=o.L1=o.R0=o.R1=;
o.L0=(l.L0&r.L1)|((~l.L0)&r.L0);
o.L1=(l.L1&r.L1)|((~l.L1)&r.L0);
o.R0=(r.R0&l.R1)|((~r.R0)&l.R0);
o.R1=(r.R1&l.R1)|((~r.R1)&l.R0);
return o;
} void build(int o,int l,int r){
if(r==l){
v[o].L0=v[o].R0=opr(,opt[rak[l]],val[rak[l]]);
v[o].L1=v[o].R1=opr(-,opt[rak[l]],val[rak[l]]);
}else{
int mid=l+r>>;
build(lch,l,mid),build(rch,mid+,r);
v[o]=merge(v[lch],v[rch]);
}
} void update(int o,int l,int r,int x){
if(r==l){
v[o].L0=v[o].R0=opr(,opt[rak[l]],val[rak[l]]);
v[o].L1=v[o].R1=opr(-,opt[rak[l]],val[rak[l]]);
}else{
int mid=l+r>>;
if(x<=mid)update(lch,l,mid,x);
else update(rch,mid+,r,x);
v[o]=merge(v[lch],v[rch]);
}
} Node query(int o,int l,int r,int x,int y){
if(l>=x&&r<=y)return v[o];
else{
int mid=l+r>>,pd=false;
Node ans;
if(x<=mid)ans=query(lch,l,mid,x,y),pd=true;
if(y>mid){
if(pd)ans=merge(ans,query(rch,mid+,r,x,y));
else ans=query(rch,mid+,r,x,y);
}
return ans;
}
} Node solve(int x,int y){
int cnt1=,cnt2=;
while(tp[x]!=tp[y]){
if(dep[tp[x]]>dep[tp[y]]){
ans1[++cnt1]=query(,,n,tid[tp[x]],tid[x]);
x=fa[tp[x]];
}
else{
ans2[++cnt2]=query(,,n,tid[tp[y]],tid[y]);
y=fa[tp[y]];
}
}
if(dep[x]<dep[y])
ans2[++cnt2]=query(,,n,tid[x],tid[y]);
else
ans1[++cnt1]=query(,,n,tid[y],tid[x]);
for(int i=;i<=cnt1;i++)
swap(ans1[i].L0,ans1[i].R0),swap(ans1[i].L1,ans1[i].R1);
Node sum;
if(cnt1)sum=ans1[];
else sum=ans2[cnt2];
for(int i=;i<=cnt1;i++)sum=merge(sum,ans1[i]);
if(cnt1&&cnt2)sum=merge(sum,ans2[cnt2]);
for(int i=cnt2-;i>=;i--)sum=merge(sum,ans2[i]);
return sum;
} int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;i++)
scanf("%d%llu",opt+i,val+i);
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%d%d%llu",&ot,&x,&y,&z);
if(ot==){
Node a=solve(x,y);
unsigned LL ans=;
for(int j=;j>=;j--){
if(a.L0&(1ULL<<j))ans+=1ULL<<j;
else if(a.L1&(1ULL<<j)&&(1ULL<<j)<=z)
ans+=1ULL<<j,z-=1ULL<<j;
}
printf("%llu\n",ans);
}
if(ot==){
opt[x]=y,val[x]=z;
update(,,n,tid[x]);
}
}
}

可怕!!

2017.8.1 Noip2018模拟测试赛(十七)的更多相关文章

  1. 2017.8.2 Noip2018模拟测试赛(十八)

     日期: 八月二日  总分: 300分  难度: 提高 ~ 省选  得分: 40分(又炸蛋了!!) 题目列表: T1:分手是祝愿 T2:残缺的字符串 T3:树点涂色 赛后心得: 哎,T1求期望,放弃. ...

  2. 2018.8.8 Noip2018模拟测试赛(二十一)

    日期: 八月七号  总分: 300分  难度: 提高 ~ 省选    得分: 112分(OvO) 题目目录: T1:幸福的道路 T2:Solitaire T3:Flags 赛后心得: 第一题裸树d啊! ...

  3. 2018.8.7 Noip2018模拟测试赛(二十)

    日期: 八月七号  总分: 300分  难度: 提高 ~ 省选    得分: 100分(呵呵一笑) 题目列表: T1:SS T2:Tree Game T3:二元运算 赛后反思: Emmmmmm…… 开 ...

  4. 2018.8.6 Noip2018模拟测试赛(十九)

    日期: 八月六号  总分: 300分  难度: 提高 ~ 省选    得分: 10分(MMP) 题目目录: T1:Tree T2:异或运算 T3:Tree Restoring 赛后反思: Emmmmm ...

  5. 2018.7.31 Noip2018模拟测试赛(十六)

     日期: 七月最后一天  总分: 300分  难度: 提高 ~ 省选  得分: 30分(少的可怜) 我太弱了:(题目目录) T1:Mushroom追妹纸 T2:抵制克苏恩 T3:美味 失分分析:(QA ...

  6. noi2019模拟测试赛(四十七)

    noi2019模拟测试赛(四十七) T1与运算(and) 题意: ​ 给你一个序列\(a_i\),定义\(f_i=a_1\&a_2\&\cdots\&a_i\),求这个序列的所 ...

  7. [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania

    [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...

  8. [CSP-S模拟测试]:赛(贪心+三分)

    题目描述 由于出题人思维枯竭所以想不出好玩的背景.有$n$个物品,第$i$个物品的价格是$v_i$,有两个人,每个人都喜欢$n$个物品中的一些物品.要求选出正好$m$个物品,满足选出的物品中至少有$k ...

  9. [NOIP2018模拟赛10.16]手残报告

    [NOIP2018模拟赛10.16]手残报告 闲扯 炉石乱斗模式美滋滋啊,又颓到好晚... 上来T2先敲了树剖,看T1发现是个思博DP,然后没过大样例,写个暴力发现还是没过大样例!?才发现理解错题意了 ...

随机推荐

  1. SQL 隔离级别

    在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的.较低级别的隔离通常可以执行更高的并发,系统的开销也更低. 简单的介绍四种隔离级别 ...

  2. C#4.0中的dynamic关键字和ExpandoObject对象

    dynamic最大的特点我想莫过于在它的类型在运行时才确定,这也是它与往静态类型关键字的最大区别.如果你在你的代码操作中用到了dynamic关键字去定义一个变量时,那么这个变量在编译的时候编译器不会对 ...

  3. Bootstrap历练实例:默认的面板(Panels)

    Bootstrap 面板(Panels) 本章将讲解 Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素 ...

  4. 01_6_SERVLET如何从上一个页面取得参数

    01_6_SERVLET如何从上一个页面取得参数 1. sevlet实现 public void doGet(HttpServletRequest request, HttpServletRespon ...

  5. ubuntu14.04搭建LAMP环境(nginx,php,mysql,linux)详解

    最近更换开发环境至ubuntu,整理开发环境和常用软件的安装配置(更新排版) 以下安装过程经过多次操作得出,参照步骤进行操作即可 一.LAMP基本环境搭建 1 切换root账号 sudo su 2,安 ...

  6. C++:100阶乘数组输出

    #include <iostream> using namespace std; int main(){ int i =1; int a[2048]={0}; while(i !=101) ...

  7. python入门:while 循环的基本用法

    #!/usr/bin/env python # -*- coding:utf-8 -*- #while 循环的作用 import time while True: ") time.sleep ...

  8. Boostrap的自适应功能

    其实理解栅栏模式之后,自适应功能就简单很多了,根据浏览器的大小,Boostrap有四种栅栏类名提供使用,用法与Css样式表类名选择器样式调用是一样的: xs:col-xs-1 ~ col-xs-12, ...

  9. 【android】签署应用采用相同证书的用处

    在应用的预期生命周期内,您应使用相同证书签署所有 APK 应用升级:当系统安装应用的更新时,它会比较新版本和现有版本中的证书.如果证书匹配,则系统允许更新.如果您使用不同的证书签署新版本,则必须为应用 ...

  10. HDU 4348 To the moon 主席树

    题意: 给出一个长度为\(n(n \leq 10^5)\)的序列,最开始时间\(t=0\),支持下面几个操作: \(C \, l \, r \, d\):将区间\([l,r]\)每个数都加上\(d\) ...