2017.8.1 Noip2018模拟测试赛(十七)
|
日期: |
八月第一天 |
总分: |
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模拟测试赛(十七)的更多相关文章
- 2017.8.2 Noip2018模拟测试赛(十八)
日期: 八月二日 总分: 300分 难度: 提高 ~ 省选 得分: 40分(又炸蛋了!!) 题目列表: T1:分手是祝愿 T2:残缺的字符串 T3:树点涂色 赛后心得: 哎,T1求期望,放弃. ...
- 2018.8.8 Noip2018模拟测试赛(二十一)
日期: 八月七号 总分: 300分 难度: 提高 ~ 省选 得分: 112分(OvO) 题目目录: T1:幸福的道路 T2:Solitaire T3:Flags 赛后心得: 第一题裸树d啊! ...
- 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.7.31 Noip2018模拟测试赛(十六)
日期: 七月最后一天 总分: 300分 难度: 提高 ~ 省选 得分: 30分(少的可怜) 我太弱了:(题目目录) T1:Mushroom追妹纸 T2:抵制克苏恩 T3:美味 失分分析:(QA ...
- noi2019模拟测试赛(四十七)
noi2019模拟测试赛(四十七) T1与运算(and) 题意: 给你一个序列\(a_i\),定义\(f_i=a_1\&a_2\&\cdots\&a_i\),求这个序列的所 ...
- [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania
[2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...
- [CSP-S模拟测试]:赛(贪心+三分)
题目描述 由于出题人思维枯竭所以想不出好玩的背景.有$n$个物品,第$i$个物品的价格是$v_i$,有两个人,每个人都喜欢$n$个物品中的一些物品.要求选出正好$m$个物品,满足选出的物品中至少有$k ...
- [NOIP2018模拟赛10.16]手残报告
[NOIP2018模拟赛10.16]手残报告 闲扯 炉石乱斗模式美滋滋啊,又颓到好晚... 上来T2先敲了树剖,看T1发现是个思博DP,然后没过大样例,写个暴力发现还是没过大样例!?才发现理解错题意了 ...
随机推荐
- java从键盘输入三个整数,实现从小到大排序
package study01; import java.util.Scanner; public class Sort { /** * 需求:由键盘输入三个整数分别存入变量a.b.c,对他们进行 排 ...
- matplotlib绘图(四)
控制文字属性的方法: 所有的方法都会返回一个matplotlib.text.Text对象 文本注释: annnotate() xy参数设置箭头指示的位置,xytext参数设置注释文字的位置 arro ...
- mariadb多源主从复制错误跳过.md
mysql 的主从错误跳过和mariadb的多源主从复制错误跳过操作不同,请注意: 更改会话的default_master_connection变量 STOP SLAVE 'slave_account ...
- destoon 支付异步接口文件 notify.php 调试方式
在if($verify_result) { 之前复制这三个变量 就可以直接访问notify.php 启用调试模式 或者 逐步echo 相关变量来调试 错误原因 notify.php没有入口文件 是 ...
- virtualbox安装win7系统报错(“FATAL:No bootable medium found!”)
virtualbox属于傻瓜式安装虚拟系统,但博主安装win7系统时,无论怎么调试都还是出现截图所述样式,网上教程很多,但是都不行,其实只有一个根本原因安装的iso镜像不是原生镜像,下载的镜像已经是被 ...
- redis列表,字典,管道,vue安装,创建项目
redis mysql,redis,mogondb 1.mysql,oracle:关系型数据库,有表概念 2.redis,mongodb/nosql:非关系型数据库 没有表概念 mongodb存储在硬 ...
- Linux学习-SRPM 的使用 : rpmbuild (Optional)
新版的 rpm 已经 将 RPM 与 SRPM 的指令分开了,SRPM 使用的是 rpmbuild 这个指令,而不是 rpm 喔! 利用默认值安装 SRPM 文件 (--rebuid/--recomp ...
- kettle-批量同步表数据
一.实验目标 利用kettle实现从mysql数据库中的dbf库批量同步表到dbm库(全量同步) 二.实验环境 dbf 库中表f1.f2.f3 .f1中1条数据,f2中100条数据,f3中2条数据 ...
- HDU 5525 Product 数论
题意: 给出一个长度为\(n(1 \leq n \leq 10^5)\)的序列\(A_i\),\(N=\prod\limits_{i=1}^{n}i^{A_i}\).求\(N\)的所有约数的乘积. 分 ...
- BugBash活动分享
此文已由作者夏君授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. BugBash源至微软概念,翻译为<缺陷大扫除>,顾名思义是集中大家力量全面清扫Bug,确保产品质 ...