比特镇旅游(Tourist Attractions)【暴力+Bitset 附Bitset用法】
Online Judge:NOIP2016十连测第一场 T2
Label:暴力,Bitset
题目描述
在美丽的比特镇一共有n个景区,编号依次为1到n,它们之间通过若干条双向道路连接。
Byteasar 慕名来到了比特镇旅游,不过由于昂贵的门票费,他只能负担起 4 个景区的门票费。他可以在任意景区开始游览,然后结束在任意景区。
Byteasar 的旅游习惯比较特殊,一旦他路过了一个景区,他就一定会进去参观,并且他永远不会参观同一个景区两次。所以他想知道,有多少种可行的旅游路线,使得他可以恰好参观 4 个景区呢?即,有多少条简单路径恰好经过了 4 个点。
输入
第一行包含两个整数n,表示景区的总数。
第2至第n+1行,每行一个长度为n的01字符串,第i+1行第j个字符为0表示i和j之间没有道路,为1表示有一条道路。
输入数据保证\((i,j)\)的连接情况等于\((j,i)\)的连接情况,且\((i,i)\)恒为0。
输出
输出一行一个整数,即可行的路线总数。
样例
Input
4
0101
1010
0101
1010
Output
8
说明/提示
8 条路线分别为:
1->2->3->4,4->3->2->1,
2->3->4->1,1->4->3->2,
3->4->1->2,2->1->4->3,
4->1->2->3,3->2->1->4。
对于40%数据,\(n<=50\)
对于70%数据,\(n<=300\)
对于100%数据,\(n<=1500\)
题解
40pts
\(O(N^4)\)枚举四个点。
70pts
\(O(N^3)\)。
考虑枚举中间两个点\(p2,p3\),现在要找到符合条件的对数{\(p1,p4\)}。需要满足的条件是这四个点两两都不相同。
设\(cnt[i]\)表示与i直接连通的点的个数(就是字符串中含1个数),\(same[i][j]\)表示与i,j都直接相连的点的个数(就是两个字符串对应位都为1的位数)。
那么上面的符合条件的对数{\(p1,p4\)}就是\((cnt[p2]-1)*(cnt[p3]-1)-same[p2][p3]\)。都减一是因为\(p2,p3\)互相相连,新选的\(p1,p4\)不能跟这两个重了。
上面的枚举是\(O(N^2)\)的,预处理\(same[][]\)是\(O(N^3)\)的。
100pts
主要瓶颈在于\(same[][]\)的预处理,其实预处理的时候就马上想到用\(Bitset\)去优化常数,快速得到这个值,但是考试的时候觉得应该有\(N^2\)解法,结果Claris的正解就是这东西???。
所以利用\(Bitset\)二进制存储,计算两者与运算结果中1的个数。
复杂度为\(O(\frac{n^3}{64})\),对于n<=1500的数据没问题。
#include<bits/stdc++.h>
using namespace std;
const int N=1510;
int n,cnt[N];
bitset<N>a[N];
int main(){
scanf("%d",&n);
register int i,j;char c;
for(i=1;i<=n;i++)for(j=1;j<=n;j++){
c=getchar();
while(c!='0'&&c!='1')c=getchar();
a[i][j]=c-'0';
cnt[i]+=c-'0';
}
long long ans=0;
for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)if(a[i][j]==1){
ans+=1ll*(cnt[i]-1)*(cnt[j]-1)-1ll*(a[i]&a[j]).count();
}
printf("%lld\n",ans<<1);
}
END
整理一下\(Bitset\)的用法。参考博客->
定义/初始化
<>
中填的类似数组大小,后面可以开成单个变量,也可以开成一个数组。
bitset<LEN>a;
bitset<2333>b[N];
初始化大概有如下几种方式。
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("test.out","w",stdout);
//用string(似乎只能包含01,不然运行时会报错)
bitset<10>a (string("11011"));
cout<<"#1:"<<a<<endl;
//用整数(转为二进制)
a=123;
cout<<"#2:"<<a<<endl;
//直接像数组那样赋值(下标从0开始,长度为10)
for(int i=0;i<=9;i++){
int o;scanf("%d",&o);//测试时输入1 0 1 0 0 0 1 1 0 1
a[i]=o;
}
cout<<"#3:"<<a<<endl;
}
输出结果
#1:0000011011
#2:0001111011
#3:1011000101
运算操作
\(Bitset\)支持所有位运算。包括异或^
、或|
、与&
、左移<<
、右移>>
等。
常用函数
查询类
1.返回1的个数
a.count();
2.返回是否有1
a.any();
操作类
3.全部变成1
a.set();
4.将右数第\(i+1\)位变成1(实际上就是将二进制的第i位变成1,下标从0开始)
a.set(i);
//例: a.set(2) 0000000100
5.全部变为0(()
中间填数字时指定某一位,同上)
a.reset();
6.取反(()
中间填数字时指定某一位,同上)
a.flip();
至于常数优化是多少,好像跟机器位数有关(32/64)。
比特镇旅游(Tourist Attractions)【暴力+Bitset 附Bitset用法】的更多相关文章
- [CSP-S模拟测试]:Tourist Attractions(简单图论+bitset)
题目描述 在美丽的比特镇一共有$n$个景区,编号依次为$1$到$n$,它们之间通过若干条双向道路连接.$Byteasar$慕名来到了比特镇旅游,不过由于昂贵的门票费,他只能负担起$4$个景区的门票费. ...
- csp-s模拟48,49 Tourist Attractions,养花,画作题解
题面:https://www.cnblogs.com/Juve/articles/11569010.html Tourist Attractions: 暴力当然是dfs四层 优化一下,固定两个点,答案 ...
- [JSOI2010]连通数 (dfs或tarjan或bitset)+bitset学习
题目描述 输入格式 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. 输出格式 输出一行一个整数,表示该图的连通数. 样例 样 ...
- 【JZOJ4857】Tourist Attractions(Bitset)
题意:给定一个n个点的无向图,求这个图中有多少条长度为4的简单路径. n<=1500 思路: #include<map> #include<set> #include&l ...
- D. 旅游景点 Tourist Attractions 状压DP
题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD 不希望在刚吃过一顿大餐之后立刻去下一 ...
- 旅游景点 Tourist Attractions 题解
题面在这里 再次破了纪录,连做了3天... 让我们从头来一点一点分析 1.预处理 先看题面,乍一看貌似是个图论题,有n个点m条边,给定一些必须经过的点和强制经过顺序,求一条最短路 我们发现n和m都比较 ...
- 牛客网提高组模拟赛第七场 T3 洞穴(附bitset介绍)
就是DP. 我们可以很简单的想到要枚举中间点,进行边数的转移. 但是因为边长数据范围很大,所以我们考虑log的倍增. 状态设计为\(dp[i][j][k]\),为从节点\(i\)走\(2^k\)步能否 ...
- 比特镇步行(Walk)【虚点+bfs+dfs】
Online Judge:NOIP2016十连测第一场 T3 Label:虚点,bfs,dfs 题目描述 说明/提示 对于100%数据,\(n<=200000\),\(m<=300000\ ...
- LYDSY模拟赛day1 Tourist Attractions
/* 假设路径是 a − b − c − d,考虑枚举中间这条边 b − c,计 算有多少可行的 a 和 d. 设 degx 表示点 x 的度数,那么边 b − c 对答案的贡献为 (degb − 1 ...
随机推荐
- CF982F The Meeting Place Cannot Be Changed
题意:给你一张有向图,某人会任意选择起点然后走无穷多步,问是否存在一个点(要求输出)不管他起点在何处怎么走都必经?n<=100005,m<=500005. 标程: #include< ...
- js清空input file值
项目进行导入操作,如果第一次导入某个文件会触发导入操作,但是第二次导入重复该文件,不会触发操作. 分析了原因,是因为上一次file里选择的文件路径值与本次选择的文件路径值是一样的,值没有改变所以导致f ...
- 关于OpenLiveWriter出错的修补方法
OpenLiveWriter使用一段时间后可能会打不开,提示错误如下: 这是只需要把电脑的.net更新到4.6以上版本就可以了.
- JavaScript - setTimeout()和setInterval()
setTimeout() 和 setInterval() 方法, 用于在指定的毫秒数后调用函数或表达式 // 1秒钟后执行 function(), 只执行一次 var a = setTimeout(f ...
- java 自加和短路问题 几个例子
x++可以看做一个独立的变量 如int a=x++;x的值先把他赋值给x++然后X++再赋值a,最后x再自加1 ++X int a=++ X 先自加1 x的值赋值给++x然后++x再赋值a ...
- lombok使用手册
lombok使用手册: 1.安装插件 1.1.idel: 1.2.使用lombok还需要引用相关jar包 参考网址:https://projectlombok.org/features/all 2.注 ...
- 0922CSP-S模拟测试赛后总结
连发三篇爆炸实录我的心态竟然还这么好…… 昨天题目的D2.稍难. 这也不是我连续拿倒数第一的理由. T1不会.赛时硬写了一个30分的三次方暴力.还有一个地方写挂了.如果不是数据足够水我就爆零了. 也就 ...
- Ubuntu-WPS无法输入中文
WPS无法输入中文 原因:环境变量未正确设置 $ vi /usr/bin/wps,添加以下内容: #!/bin/bash export XMODIFIERS="@im=fcitx" ...
- badboy录制添加检查点
前提条件 安装badboy 下载地址:http://www.badboy.com.au/download/index 录制脚本 1.例:录制www.baidu.com 2.打开badboy工具输入录制 ...
- PHP实现对短信验证码发送次数的限制
http://www.jb51.net/article/94878.htm 对用户获取短信验证码的手机号.ip.和浏览器(使用唯一标识)进行限制.本文介绍的方法是对用户每天只能通过同一浏览器或同一ip ...