国庆 day 6 下午
1.数组异或
(xorarray.pas/c/cpp)
(xorarray.in/out)
时间限制:2s/空间限制:256M
【题目描述】
xor——异或,和 and 与or 一样,是一种重要的逻辑运算,他的运算规律是 0 xor 0 = 0,1 xor 1 = 0,1 xor 0 = 1,0 xor 1 = 1
两个整数之间的异或是将两个整数转化成二进制,对他们的每一位分别进行 xor 操作,例:6(110) xor 13(1101) = 11(1011)
现在我们要介绍一种新的操作——数组异或,将两个相同大小(假设都为n)的数组A、B异或成一个新数组C,则新数组必满足:
现在给你数组大小n,和两个数组A,B
求他们的异或数组C
由于最终答案可能过大,你需要对C的每个元素对109+7取模
【输入格式】(xorarray.in)
一共3行。
第一行一个正整数。
接下来两行每行个正整数,表示数组A、B。
【输出格式】(xorarray.out)
一共行,个正整数,表示数组C。
【输入输出样例1】
xorarray.in |
xorarray.out |
7 20670 1316 25227 8316 21095 28379 25235 19745 6535 14486 5460 15690 1796 12403 |
7583 52096 161325 276944 453024 675974 958287 |
【数据规模约定】
对于50%的数据,N≤100
对于全部的数据,N≤100000
思路:二进制拆分,维护一个二进制前缀和。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100100
#define mod 1000000007
using namespace std;
int n;
int bit[];
int a[MAXN],b[MAXN],c[MAXN];
int suma[MAXN][],sumb[MAXN][];
int finda(int r,int wh){
long long tot=;
for(int i=;i<=;i++)
if(wh&bit[i]) tot=(tot+1ll*(r-suma[r][i])*bit[i])%mod;
else tot=(tot+1ll*suma[r][i]*bit[i])%mod;
return int(tot%mod);
}
int findb(int r,int wh){
long long tot=;
for(int i=;i<=;i++)
if(wh&bit[i]) tot=(tot+1ll*(r-sumb[r][i])*bit[i])%mod;
else tot=(tot+1ll*sumb[r][i]*bit[i])%mod;
return int(tot%mod);
}
int main(){
freopen("xorarray.in","r",stdin);
freopen("xorarray.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
int x=a[i],len=;
while(x){
suma[i][len++]=suma[i-][len]+(x&);
x/=;
}
for(int j=len;j<=;j++) suma[i][j]=suma[i-][j];
}
for(int i=;i<=n;i++){
scanf("%d",&b[i]);
int x=b[i],len=;
while(x){
sumb[i][len++]=sumb[i-][len]+(x&);
x/=;
}
for(int j=len;j<=;j++) sumb[i][j]=sumb[i-][j];
}
bit[]=;
for(int i=;i<=;i++) bit[i]=bit[i-]<<;
c[]=a[]^b[];
for(int k=;k<=n;k++){
c[k]=c[k-];
c[k]=(c[k]+finda(k-,b[k]))%mod;
c[k]=(c[k]+findb(k,a[k]))%mod;
}
for(int i=;i<=n;i++) cout<<c[i]<<" ";
}
2.侦探游戏
(detective.pas/c/cpp)
(detective.in/out)
时间限制:1s/空间限制:256M
【题目描述】
小W最近沉迷一个侦探游戏,在这个游戏中会不断出现命案,而小W作为主角,需要不断地收集各种关键证据,只有当所有的关键证据都被找到,你才能 驳倒所有人错误的判断,找出真正的凶手。
一共有个关键证据以及条信息,每条信息如下所示 : 如果你已经掌握了证据 i ,那么你可以通过 k 个时间的搜索和推理得到证据 j ,同样的,如果你掌握了证据 j 你也可以通过 k 个时间得到证据 j 。
游戏开始时玩家通过初步观察现场已经得到了证据1,于此同时,每个玩家在游戏开始阶段时都能获得一个特殊技能来加快游戏进度,增加趣味性。小 W 选了一个他以前从来没用过的技能 : 好运。这是一个被动技能,系统会在游戏开始时选定一对证据(a,b)当小W发现其中一个证据的时候,他会很好运地立即获得另外一个证据(不计入时间)。
但是这个技能是完全随机的,小W完全不知道进入游戏后系统会挑选哪一对证据,他希望你能帮助他算出他花在本轮游戏上的时间的期望值,这样他心里能有点B数。
提供的信息保证 : i不会等于j,每个k值都互不相同,个证据都能被得到。
【输入格式】(detective.in)
一共行。
第一行两个正整数,表示证据数量和信息数量。
接下来行,每行三个数字i,j,k表示一个信息
【输出格式】(xorarray.out)
一共行,个整数(期望值是实数,但这里请直接保留0位小数输出)
【输入输出样例】
detective.in |
detective.out |
3 1 2 3 1 3 2 2 3 5 |
2.3333 |
【数据规模约定】
对于的数据,
对于的数据,
对于全部的数据,
【样例解释】
答案应该是2.33333......,取2
以下思路来自xxy大佬的博客。
60分做法:
先做一遍最小生成树
枚举两个点i,j,那么替换掉的是最小生成树上i,j路径上权值最大的边
倍增维护
时间复杂度:O(n*n*logn)
100分做法:
换一个角度,考虑被替换掉的边的贡献
边e要想被替换掉,那么点 i,j 要满足两个条件:
① 设e的两端点所连的子树为u,v,i∈u,j∈v
② e的边权是连通 i,j 必经之路(最短路)上边权最大的边
怎么找这条边?——Kruscal算法
Kruscal算法每次找还没有加进去的权值最小的边,所以满足必经之路
还没有加进去的边权最小的边,是已加进去的边权最大的边,所以满足路径上边权最大
所以,设最小生成树的总权值为sum,设当前边权为w,当前边连接的两点的集合大小分别为 s1、s2
ans=(sum*n*(n-1)- 2*Σ s1*s2*w)/(n*(n-1))
n*(n-1):任意选两个点共有这些选法
Σ 前乘2:u,v 和 v,u 算不同的方案
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 20010
#define N 100010
using namespace std;
int n,m;
long long sum,cnt;
int fa[M],size[M];
struct nond{
int u,v,w;
}edge[N];
int cmp(nond a,nond b){
return a.w<b.w;
}
int find(int k){
if(fa[k]==k) return k;
return fa[k]=find(fa[k]);
}
int main(){
freopen("detective.in","r",stdin);
freopen("detective.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
sort(edge+,edge++m,cmp);
for(int i=;i<=n;i++) fa[i]=i,size[i]=;
for(int i=;i<=m;i++){
int dx=find(edge[i].u);
int dy=find(edge[i].v);
if(dx==dy) continue;
fa[dy]=dx;
sum+=edge[i].w;
cnt+=1ll*size[dx]*size[dy]*edge[i].w;
size[dx]+=size[dy];
}
printf("%.2lf",sum-cnt*2.0/(n*(n-)));
}
3.棋盘迷宫
(boardgame.pas/c/cpp)
(boardgame.in/out)
时间限制:5s/空间限制:256M
【题目描述】
小A和小Z是非常要好的朋友,而且他们都对迷宫游戏非常有兴趣。他们经常在自习课上用迷宫来打发时间(两位都是学习效率400%的dalao,大家切记不要模仿)。
他们的迷宫非常简单,又被他们叫做是棋盘迷宫,迷宫本身是一个N*M大小的棋盘,从左往右列数不断加大,从上往下行数不断增大,故左上角的坐标为(1, 1),右下角的坐标为(N,M)。当你处在坐标为(X,Y)的格子里时,你只能走到(X+1,Y)或(X,Y+1),即只能往右走或者往下走(当然你也不能走出棋盘)。同时部分格子中有障碍物,这样的格子是不能经过的,用‘#’代表,能正常通行的格子由‘.’代表。
每一轮游戏先由其中一人选定起点和终点,由另外一个人来完成)。但是他们很快发现,并不是每次都能找到一条从起点到达终点的路径,两位dalao的注意力立刻从游戏转移到了如何快速判断路径是否存在这个问题上。
当然dalao们瞬间得到了算法,不过他想考考你,如果你能顺利解决,也许就能得到他们两个的签名哦!(据说是最高级别的因果律护身符,能让人逢考必过)
【输入格式】(boardgame.in)
一共行。
第一行两个正整数为,表示棋盘迷宫的行列。
接下来行,每行一个长度为的字符串,由‘#’‘.’两种字符组成
接下来1行,一个正整数,表示询问的个数
接下来行,每行四个正整数x1,y1,x2,y2询问点(x1,y1)到(x2,y2)是否有一条合法的路径
数据保证(x1,y1)(x2,y2)所在的位置都是‘.’,同时x1<=x2,y1<=y2
【输出格式】(boardgame.out)
一共行,每行一个字符串或者,对应每一个询问的答案。
【输入输出样例】
boardgame.in |
boardgame.out |
4 4 .... ..#. .##. .... 3 2 2 4 4 2 1 4 4 1 2 4 4 |
No Yes Yes |
【数据规模约定】
对于40%的数据,N,M<=100,Q<=1000
对于全部的数据,N,M<=500,Q<=1000000
以下思路来自xxy大佬的博客。
分治+DP+bitset
若点(x1,y1)能访问到点(x2,y2)
假设x1<=x2,y1<=y2
那么(x1,y1)往右下扩展,(x2,y2)往左上扩展,两个点一定在中间某一行相遇
所以可以利用分治的思想枚举相遇的那一行
如果x1和x2都在枚举的这一行的上面,那就扔到左边
如果x1和x2都在枚举的这一行的下面,那就扔到右边
左边和右边的分别继续分治下去
如果x1和x2一个在上面,一个在下面,那就判断这两个点能否在这一行相遇
能在这一行相遇,两个点一定能相遇
反之,一定不能相遇
如何判断 ?
假设当前枚举的相遇行为mid,
f[i][j][k]=0/1表示第i行第j列的点,向右下扩展,能否扩展到第mid行的第k列
g[i][j][k]=0/1表示第i行第j列的点,向左上扩展,能否扩展到第mid行的第k列
若 f[x1][y1][k] 和 g[i][j][k] 有一个k同时为true,那么两个点就可以相遇
第三维可以用bitset简化
f的转移:
预处理:f[mid][j][j]=第mid行第j列是否有障碍
倒叙枚举mid行之上的i,j,f[i][j]|=f[i][j+1],f[i][j]|=f[i+1][j]
g的转移类似,
正序枚举mid行之下的,加号改成减号即可
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 501
#define M 1000000
using namespace std;
int n,m,Q;
char s[MAXN];
bool map[MAXN][MAXN],ans[M];
bitset<MAXN>f[MAXN][MAXN],g[MAXN][MAXN];
struct nond{
int sx,sy,tx,ty,id;
}p;
void slove(vector<nond>vec,int l,int r){
if(l>r) return ;
int mid=(l+r)/;
for(int i=mid;i>=l;i--)
for(int j=m;j;j--){
f[i][j]=;
if(!map[i][j]) continue;
if(i==mid) f[i][j].set(j);
else f[i][j]|=f[i+][j];
if(j!=m) f[i][j]|=f[i][j+];
}
for(int i=mid;i<=r;i++)
for(int j=;j<=m;j++){
g[i][j]=;
if(!map[i][j]) continue;
if(i==mid) g[i][j].set(j);
else g[i][j]|=g[i-][j];
if(j!=) g[i][j]|=g[i][j-];
}
vector<nond>vl,vr;
for(vector<nond>::iterator it=vec.begin();it!=vec.end();it++){
p=*it;
if(p.tx<mid) vl.push_back(p);
else if(p.sx>mid) vr.push_back(p);
else ans[p.id]=(f[p.sx][p.sy]&g[p.tx][p.ty]).any();
}
slove(vl,l,mid-);
slove(vr,mid+,r);
}
int main(){
freopen("boardgame.in","r",stdin);
freopen("boardgame.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%s",&s);
for(int j=;j<m;j++)
if(s[j]=='.') map[i][j+]=;
else map[i][j+]=;
}
scanf("%d",&Q);
vector<nond>vec;
for(int i=;i<=Q;i++){
scanf("%d%d%d%d",&p.sx,&p.sy,&p.tx,&p.ty);
p.id=i;
vec.push_back(p);
}
slove(vec,,n);
for(int i=;i<=Q;i++)
if(ans[i]) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
/*
4 4
....
..#.
.##.
....
3
2 2 4 4
2 1 4 4
1 2 4 4
*/
国庆 day 6 下午的更多相关文章
- 国庆 day 7 下午
思路:见博客. #include<iostream> #include<cstdio> #include<cstring> #include<algorith ...
- 国庆 day 2 下午
最大值(max) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度为n的 ...
- 国庆 day 1 下午
一道图论好题(graph) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图, ...
- 国庆 day 3 下午
a[问题描述] 你是能看到第一题的 friends 呢. ——hja 给你一个只有小括号和中括号和大括号的括号序列,问该序列是否合法.[输入格式] 一行一个括号序列.[输出格式] 如果合法,输出 OK ...
- 2018国庆YALI集训游记
想了想,像之前那样简略地叙述题意和做法,根本没讲清楚,没有任何意义,还不如写写自己的感受. 感觉YALI真的是一所挺不错的学校吧.总是能有一机房的julao轮番吊打你,总是能有集训队的奆佬来给你出dl ...
- 2016.10.4初中部下午NOIP普及组比赛总结
2016.10.4初中部下午NOIP普及组比赛总结 这次的题有些水,只是第四题有点坑. 题目: 比赛:AC+0+AC+50=250 改题:AC+AC+AC+50=350 一.Bill 满地都是水 题目 ...
- 票房和口碑称霸国庆档,用 Python 爬取猫眼评论区看看电影《我和我的家乡》到底有多牛
今年的国庆档电影市场的表现还是比较强势的,两名主力<我和我的家乡>和<姜子牙>起到了很好的带头作用. <姜子牙>首日破 2 亿,一举刷新由<哪吒之魔童降世&g ...
- 搞了我一下午竟然是web.config少写了一个点
Safari手机版居然有个这么愚蠢的bug,浪费了我整个下午,使尽浑身解数,国内国外网站搜索解决方案,每一行代码读了又想想了又读如此不知道多少遍,想破脑袋也想不通到底哪里出了问题,结果竟然是web.c ...
- System.DateUtils 3. IsPM、IsAM 判断是否为上、下午
编译版本:Delphi XE7 function IsPM(const AValue: TDateTime): Boolean; inline;function IsAM(const AValue: ...
随机推荐
- 2017-2-10 bash基础脚本
练习:写一脚本,实现如下功能: 1.让用户通过键盘输入一个用户名,如果用户不存在就退出: 2.如果其UID等于其GID,就说它是个"good guy" 3.否则,就说它是个“bad ...
- Django REST framework 自定义字段
自定义字段 继承 Field 类 覆盖父类中的方法 to_representation() 调用该方法将初始数据类型转换为基本的可序列化数据类型 to_internal_value() 调用该方法将原 ...
- Generator 简介
Generator 就是一种状态机,封装多个内部状态. 执行 Generator 函数会返回一个遍历器对象(),也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数.返回的遍历器对 ...
- Docker学习总结(10)——10分钟玩转Docker
1.前言 进入云计算的时代,各大云提供商AWS,阿里云纷纷推出针对Docker的服务,现在Docker是十分火爆,那么Docker到底是什麽,让我们来体验一下. 2.Docker是什麽 Docker是 ...
- 2015 Multi-University Training Contest 3 hdu 5326 Work
Work Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 1827 Summer Holiday(强连通)
HDU 1827 Summer Holiday 题目链接 题意:中文题 思路:强连通缩点,每一个点的权值为强连通中最小值,然后入度为0的点就是答案 代码: #include <cstdio> ...
- hadoop-08-关闭THP服务
hadoop-08-关闭THP服务 #查看THP服务cat /sys/kernel/mm/redhat_transparent_hugepage/enabledcat /sys/kernel/mm/r ...
- [Transducer] Make an Into Helper to Remove Boilerplate and Simplify our Transduce API
Our transduce function is powerful but requires a lot of boilerplate. It would be nice if we had a w ...
- mysql-管理事务
一.介绍 mysql支持几种基本的数据库引擎,其中MYSQL的两种最基本的引擎MyISAM和InnoDB,其中只有InnoDB支持事务管理. 事务处理:可以用来维护数据库的完整性,他保证成批的MySQ ...
- Java读取配置文件的方式
Java读取配置文件的方式-笔记 1 取当前启动文件夹下的配置文件 一般来讲启动java程序的时候.在启动的文件夹下会有配置文件 classLoader.getResource(&qu ...