从ubuntu server 开始,配置自动分流的软路由

花了好长时间,配置好了一台软路由,现在可以自动分流,国外流量通过vps出去。我自己还造了一个dns服务器的轮子,现在可以预查一下,国内的用114,国外的用vps的那边ip作为edns_ip去查一下。这样cdn能用国内的也会尽量用国内的,还是防污染的,国外cdn也不会绕路。

我是在淘宝上买的一台专门用来做软路由的x86 的小机器。有4个网卡,j1900的cpu。其实如果有不用的机器而且有两个网卡的话,也可以搭起来。我是直接从ubuntu server 开始搭的,没有用什么固件,因为洁癖哈哈哈哈。

现在我的路由拓扑大概长这样:

        -----------              -------
        | CERNET  |              | ISP |
        -----------              -------
            ||                     ||
            nat                    nat
            ||                     ||
----------------             -----------------
|  bj00        |             |  sf01         |
| 10.56.1.0/20 |  <=======>  | 10.56.16.0/20 |
|              |             |               |
---------------              -----------------
     ||
    lan
     ||
 10.56.1.0/24

基本路由功能

Lan Interface
首先把一个网卡设置成内网的接口(interface),在路由器上这个网卡的设置可以写在/etc/network/interfaces里面,把下面内容写到里面末尾:

auto enp2s0
iface enp2s0 inet static
    address 10.56.1.1
    netmask 255.255.255.0

接下来运行sudo service networking restart 去重启,运行ip addr就可以看到新配置的接口。注意我的接口名字就叫做enp2s0,你可以通过ip addr查看你的接口名字。

其实这样就可以自动配置好到10.56.1.0/24这个子网的路由之类的。

sysconf
把这些项加到 /etc/sysctl.conf 里面

net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

前两项后面配置策略路由的时候需要用到,后面两项是允许系统接受目的地不是本地的包。重启下机器生效(其实应该某条命令也可以生效的,我一直没成功233333

dhcp 服务器
安装isc-dhcp-server

sudo apt install isc-dhcp-server

接下来配置/etc/default/isc-dhcp-server,把接口改成刚才设置的接口:

INTERFACES="enp2s0"

编辑/etc/dhcp/dhcpd.conf,把下面内容加进去:

subnet 10.56.1.0 netmask 255.255.255.0 {
    range 10.56.1.20 10.56.1.100;
    option routers 10.56.1.1;
    option domain-name-servers 10.56.1.1;
}

那个domain-name-servers,我是已经配置好了一个dns server,所以填的服务器地址,如果没配置好可以先设置成114之类的。

接下来运行sudo service isc-dhcp-server restart 重启dhcp服务器。

现在路由器的基本功能应该是已经够了,把这个网口接上交换机或ap就已经可以组建一个局域网了。也可以直接可以插上一个网线到连到你的电脑上,你就可以看到自己被分配了一个内网的ip地址,还可以ping 10.56.1.1玩一下。

nat
需要nat才可以上外网。

运行下面这条命令就可以把源是内网ip,出口是enp1s0的加上一个nat。那个enp1s0是插公网网线的那个出口。

iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE

到现在位置你获得了一个高性能x86架构的普通的路由器了233333333

=========== 坑,哪天想起来继续填。。===========

策略路由

ipset&iptables
openvpn tunnel

无污染的dns,freedns

持久化配置

FreeDNS: 利用Google 的 DNS-Over-HTTPS 来实现无污染的DNS

项目地址:https://github.com/Chenyao2333/freedns

用Node.js 写的,基于Google 的 DNS-Over-HTTPS。还实现了一个简陋的lazy 更新缓存。

比较糟糕的是有些网页用了各种cdn,各种奇怪的域名,基本上大概一个新网页就是几十的并发。但是因为缓存的存在,所以打开一次之后,再打开就非常顺畅。缓存的更新策略是当前链接小于3个的时候,就去查询被查询到的过期缓存。

我把这个架设到校内的工业云上面了,上面没有ipv6地址,我用isatap 连上了校内的ipv6 隧道。之后就可以直接查询到香港的Google 服务器,ping 的延迟在50+ ms 左右。应该可以支持小规模的访问,教育网的的同学可以把自己的地址设置到101_6_163_87 。之后有ipv6的情况下可以直接上google 之类的站点。(因为我没有设置死了edns为学校的ip,所以返回的应该是针对教育网的北京cdn,其他网络用起来可能比较慢)

遇到tentative dadfailed 的解决方案

发现无线网卡不能分配到ipv6的地址,觉得非常奇怪,通过ip addr发现被分配了几个本地的地址,并且有一个tentative dadfailed标记。

原因是因为ip地址冲突,但是非常奇怪为什么会冲突,解决方案及其暴力,就是允许接受冲突….:http://blog.clanzx.net/2013/11/16/ipv6-dad.html

新建一个/etc/sysctl.d/accept_dad.conf的文件,内容填上:

net.ipv6.conf.all.accept_dad = 0
net.ipv6.conf.default.accept_dad = 0

net.ipv6.conf.all.use_tempaddr = 0
net.ipv6.conf.default.use_tempaddr = 0

然后重启机器解决问题。

我其实还想换mac地址来着,但是不知道为啥换了以后不生效,遂放弃…

NOIP2016 Day1 天天爱跑步 题解

第一次出题好激动啊,这题是我在军训时候开脑洞想起来出的,其实一开始题目比这个难,但是我发现我做不出来了。最后经过多次迭代题目变成了这个样子。这个解法是某次ddl干不完于是去厕所冷静一发想出来的。

首先是求出来每条路径的LCA,倍增或者Tarjan都行。接下来路径变成向下和向上的路径。

先考虑向上的路径。对于节点$j$的$W_j$,只有起点距离$j$为$W_j$的路径可以被观察到。所以对于起点$S_i$,只有$deep[S_i] = deep[j] + W_j$的时候才能被$j$观察到,这样对于每个询问问题就成了:子树中有多少路径起点的深度值为$deep[j] + W_j$,且这个路径经过自己。这是个经典的离线问题,首先可以DFS一遍求出DFS序,之后一颗子树在序列上是连续的,所以相当于问一个区间有多少值为$deep[j] + W_j$,从左往右扫描一遍即可。记$pre_i$为DFS时初次访问节点$i$的dfs序,$suf_i$为退出节点$i$时的dfs序,再记录一个数组$a$,那么离线起来有这些事件:

  • 对于一个$W_j$,在扫描到$pre_j$时候记录下$a[deep[j] + W_j]$的值;扫描到$suf_j$的时候再记录下$a[deep[j]+W_j]$的值,两次做差就是$j$观察到人数
  • 对于一个向上的路径,起点为$S_i$,终点为$T_i$(这里的$T_i$是LCA不是原题的$T_i$),在扫描到$pre_{T_i}$时, 给$a[deep[S_i]]$加上1;扫描到$suf_{T_i}$时,给$a[deep[S_i]]$减去1。

类似的,对于向下的路径,有$W_j – deep[j] = total\_len – deep[T_i]$,其中$total\_len$为路径的长度。之后可以用类似的算法做出来。

 

比赛的时候有个小插曲,当时我们班组织在圆明园玩,突然微信群上看到说我题目样例描述有问题…

ymy

还有天天小朋友长这样:

tt

以及我阿甘快刷不完了

冬天的圆明园还不错

noi2015-杭州游记

####noi之前

我们提前来了几天跟着学军的大爷们一起集训,每天都处于被虐的状态。

####报到日

因为之前一直住在学军附近宾馆,所以我们并不怎么着急,就是搬了个地方。下午的时候遇到了外语的小伙伴们,和安一的那个妹子。

到了寝室发现被分到了女寝,然后被寝室的画风吓傻了,乡下人没见过世面。还在墙上发现了某个鬼畜的树。之后就是翻一翻柜子看看会不会有妹子留下的什么奇怪的物品,雾

领物品的时候打开包发现真的给我发了粉色衣服,然后激动的拿了出来,被负责迎宾的妹子笑了一番QAQ。然后不知道什么缘故,夹心选的粉色衣服并没有给他,他表示相当气愤。

####开幕式、笔试

开幕式上最大的感触就是“别人学校的妹子”。不得不说学军的妹子真的多才多艺。dzd像往常一样继续表示noip取消保送是CCF和教育部斗争的结果,但是大家的热情并不减之类的话。又说noi人数创新高,比去年多一人,似乎去年也是这么说的,CCF真机智啊,这样就可以实现每年NOI人数持续增长。C、D类的人数似乎还感受到了外快也创新高了

下午笔试,发现还是99分,并不知道哪里错了,和去年似乎一样。

下午的时候和rbw一起去操场转悠,遇到了两个妹子,操场上就我们4个人,不太好意思躲开就去要了QQ。发现里面其中一个人是mjy,看了她的成绩后被吓傻了,还是初三,感觉妹子这么厉害还怒虐男选手。

####day1

不太明白为什么要在门口排队进,感觉这样还是很挤啊。

翻开题目被吓了一跳,卧槽这画风不对,没有提答,CCF想干嘛。看了第一题画风更不对了,似乎是个真·普及难度?我又读了几遍题还是不敢动键盘。第二题看了后感觉又不对了,树剖裸题?要干嘛?第三题看完之后觉得不会,可以玩4个小时第三题。为了吸取数次比赛跪的教训,最后再写数据结构题。不过中间剩3个小时的时候觉得保险还是去给前两题写了。此时t3并没有什么进展。最后YY了一个70分的算法,感觉自己代码能力有些坑,剩40分钟才搞完。测了一下给的样例对了,又跑了一下200\300的点,都能跑出来,最后试了一下500,发现卧槽0.4s就可以出解,是我常数压的小的缘故吗?

成绩出来后梦迪300分,我也是300分,感觉不错,真·暴力出奇迹。

下午讲题的时候第二题出题人被婊的好惨,第二题有200+人AC,出题人表示如果去看一眼BZOJ就不会发生今天这个情况…

####社会活动日

先去阿里听报告,在路上导游介绍的时候我一直在玩马云不会写代码和支付裱这个梗…报告其实是从其他地方贴来的PPT换了封面,感觉应付一批一批的来听报告的人也是蛮辛苦的。

之后去西溪湿地,在车上的时候勾搭到了负责河南和贵州的妹子,她们原来是新高一的,随身还带着王后雄,感觉好厉害,感觉这预示着我NOI药丸,要回去高考。

在西溪湿地有个寻宝活动,但是可能我们走的比较慢的缘故,只发现了一张谢谢参与。不过这个似乎比河北他们拿到10张谢谢参与要强233333333。感觉西溪湿地的景色挺不错的,志愿者妹子也不错:)。玩到下午突然下起了雨,把我们都打散,学军也决定不去湿地博物馆了。在返回出口的电瓶车上和mjy坐到了一起,被吓得到处在爬。我们返回的时候发现车队停在了钉子路口,三个岔口路边都是车,并不知道哪辆是返回的车,3个方向都找了一遍才找到车,好感人。

回去之后跑去宾馆,洗澡的时候累的站不稳了,差点晕倒,感觉我的体质也是药丸。

####day2

早上4点就醒了,床上翻滚了一个小时后去上个厕所就彻底睡不着了,

恩,直接让我们进了,没有排队,可能因为去的比较早的缘故并没有感觉挤。

翻开题目,没有提答,但是两题都有部分分,感觉不对劲。发现t1似乎K=2的时候把高度作为第二个键值建哈夫曼树做就行了。敲了以后发现对于其他情况似乎只要根节点儿子满了之后也是正确的,一直在想存在不存在一种调整方案,但是并没有想到。

t2似乎没有部分分,应该是作为送分题出的吧,想了想感觉把串反过来变成后缀,之后利用后缀自动机每个节点的性质做是裸题?其实后缀自动机我仅仅停留在看懂证明的状态,其他性质全是背下来的TAT,但是发现这些性质正好够用。后缀自动机的每个节点表示一类最后一个位置集合相同,suflink还构成了一棵树,得到这个集合大小后,可以直接搞出计数。对于最大值可以维护最大,次大一类的不断上传就行,大概是个树形DP。不过似乎用全是a的数据就会卡爆栈,改成非递归的才放心。

最后一题,感觉前两问可以dp做,最后一个似乎是网络流模型。但是我比较傻逼前两问并没有敲出来…而且那个网络流我似乎也不知道怎么写,感觉并不可惜。

萌帝230,我60+100+12(卧槽还对了一些点),感觉au要悬。

讲题时出题人怒婊全场,表示昨天出t2被骂很不爽。我当时觉得考跪,就没有心情上去正面刚。t1似乎直接补0就可以解决不满的问题了,t3那个网络流是有下界最小流。

最后知道分数线整个人都跳起来了,竟然这也能au。之后梦迪去了pku,我去thu了。

####鬼畜运动会、闭幕式

运动会的时候大家表示都不太想来,最后我、萌帝、ztx、nh组了一队,玩的比较欢脱。那个毛毛虫竞技我们配合不好,之后我和萌帝就轧马步跑了过去,感觉规则并没有说必须要跳。反正最后很开心就对了。

闭幕式的时候wh说道这次比赛考查了并查集…的时候,大家一阵鼓掌,感觉NOI要变成noip普及组+数据结构专场。

吐槽一下,那个牌子的做工并没有去年深外的做工好。

不管怎样,高中生活就在最后一次NOI中结束了,感觉自己突然获得了一年自由的时间并没有什么想象的那么激动。我还没想好要怎么规划好这一年,毕竟真的玩一年不是特别好的样子。

最后贴一张图

和志愿者妹子合照

Codeforces Round 310 (Div. 2)

我脑子里全是草泥马…

####A. Case of the Zeros and Ones

题意:给你一串01串,每次可以选择一个”0”和一个”1”消掉,问最后长度最短是多少。

串的长度减去0或1最小的数量的2倍就行了。

####B. Case of Fake Numbers

题意:有n个数$a_0, a_1, …, a_{n-1}$,问是否存在一个$k$,使得满足对于所有的$i$,有$a_i + (-1)^{i}*k mod n = i$。

显然求出来对于$a_0$的$k$,之后判定一下是否全部满足就就可以了。

####C. Case of Matryoshkas

题意:有n个套娃,之后有一些已经放在桌子上嵌套在一起了。问把n个全部套在一起需要几次操作。(对于几个套在一起的如果分开只能从上方拿掉一个!差不多类似放在桌子上然后只能一个手操作。)

模拟吧,对于1开始有序的那部分不用拆开,其他都要拆。这个题意我看了好长时间才看懂TAT

####D. Case of Fugitive

题意:每个小岛在轴上是一个区间,然后有一些距离确定的桥,问是否存在一种桥使用方案使得相邻的岛之间有桥。

把相邻的岛可以接受的桥的长度搞出来,之后相等于一群区间是否有方案使得每个区间覆盖一个不同的点。区间左端点和桥一起排下序,贪心匹配一下就行了。

####E. Case of Chocolate

题意:有一个n*n的巧克力,之后从左下方到右上有一条对角线,对角下方已经被吃完了。现在有一些询问,每个询问给一个对角线上的点和一个方向(上或者左),从这个点开始朝着给定方向吃,吃到空格子结束。问每次可以吃多少个格子。

考虑向上吃对向左吃的影响,反之一样。可以发现每次向上吃完之后,可能影响的是吃的这个区间的点。而每次求向左的方案就相当于求最近的上。离散化一下用线段树实现区间更新最大值,单点求值即可。


我脑子里全是草泥马…不要问我为什么E没有过…

然后大家似乎FST的很欢脱….我下一场就可以打div1了好开心…

考前划水系列

好长时间没有写记录…感觉没有压迫感。

6.15

BZOJ 2069: [POI2004]ZAW PoPoQQQ大爷的题解 非常神奇的一道题。问题相当于从1号节点走到一个相邻节点,之后再不经过这条边走回1号节点。把这样一条路径的第一个不是1的节点记为$s$,最后一个不是1的节点记为$t$。这样就成了找一对$s,t$使得$len(1, s) + cost(s, t) + len(t, 1)$最小。去除1号节点,把点集分成两部分$A$和$B$,对于在$A$的节点$i$,其起始值为$len(1, i)$,之后做一遍dijkstra,所有$B$集合内的点$i$,可以更新答案$ans = min(ans, d[i]+len(i,1)$。这样如果每对点都不属于一个集合中做过一次最短路,就可以求得答案。对于$i$和$j$,$i \ne j$,则一定有一个二进制位不同,所以枚举二进制位,每次把这一位为1的分为一个集合,0的分为另一个集合,做一遍最短路。
查看代码

BZOJ 2525: [Poi2011]Dynamite 膜PoPoQQQ大爷的。首先肯定二分时间$T$,之后计算最小需要的点燃点的数量,验证之。处理出每每个点$i$儿子中,距离最远且有炸弹的点的距离$deepest_i$,以及从$i$点出发最远可以点燃的距离$down_i$。然后就比较显然了,看代码

BZOJ 1117: [POI2009]救火站Gas 之前做过一次,之后WA某个点弃疗了。树形dp,和上题区别是这个每个点有数量限制。维护救火站到达点$u$以后,还可以救火最大距离为$i$时,能救的点数量$have_{u,i}$。维点$u$距离为$i$的点,还没有被覆盖的点$need_{u,i}$。对于当前维护的点$u$,$i \ge j$,$have_{u,i}$和$need_{u,j}$可以抵消掉,即选择一部分救火站去覆盖点。当$i = j$的时候,一定要抵消掉,否则向上传递后,需要救火的的距离变远,而覆盖的范围变小,变的不合法,如果此时从其兄弟或祖先来救自己的话一定不会更优。对于其他的即使向上传递后也合法,那么暂时不考虑,让传递上去。当然对于$have_{u,i}$和$need_{u,i-1}$向上传递也会变得不合法,不过要等所有$have_{u,i}$和$need_{u,i}$抵消完之后才可以抵消这个(YY证一下这个吧,对着数据调出来的结论)。之后就是各种细节了,看代码


6.16

BZOJ 3203: [Sdoi2013]保护出题人 可以发现对于每个僵尸$i$都要满足$y_n \ge \frac{\sum_i^n A_i}{x_n + (n-i)d}$。相当于求后面那个东西的最大值。把每个僵尸转化成一个点,$x$坐标为为$\sum_i^n A_i$,$y$坐标为$x_n + (n-i)d$。这样可以发现,答案是过原点与某个点的斜率最大值。一定在上凸包上,而且往前面新加入点相对位置不会变,这样维护凸包就比较方便了。之后三分求答案。不过注意这个输出的时候,直接printf保留0位小数即可,转化成long long再输出来会崩。
查看代码


6.17

BZOJ 1122: [POI2008]账本BBB 先考虑不进行移动操作时方案,如果需要把“-”变成“+”,那么一定把序列前面一部分“-”变成“+”,这样后面所有可能为负的地方值都会加2。如果需要变成“-”,则一定在最后变。之后前缀和最小的地方如果非负后,那么一定整个序列一定合法了。对于有移动的时候,快速找到最小值可以用单调队列来做。查看代码

BZOJ 1127: [POI2008]KUP 构造题。先处理每行,看看是不是有符合条件的一段(矩形的宽为1)。之后如果没有的话,把大于2K的点设置为障碍点,再找一个矩形的和大于K的。这个矩形和如果大于2K,就减去一行,一直减到符合条件位置。因为处理过每行了,所以每次减的一定小于K,所以正确。查看代码


6.20

端午节快乐

####BZOJ 2081: [Poi2010]Beads

枚举$k$,之后hash判重就可以了。从hzwer那里看到一个优化,对于反向的串不必插两次,而是把正向和反向的值乘起来。(其实我一开始不仅插两次而且怕冲突双hash了)

####BZOJ 2082: [Poi2010]Divine divisor

题太神了。第一问其实是求质因数分解的最大指数$k$。第二问有$cnt$个$p_i^{k_i}$的$k_i$与$k$相同,答案是$2^{cnt}-1$。

可以把每个数小于$10^6$的质因子搞出来,剩下的要么是一个质数,要么是一个质数的平方,要么是两个质数相乘。判断质数可以用miller-rabin做,两个质数相乘可以互相求gcd来找。如果还没有找到那么肯定是两个质数相乘且没有再其他数里面出现过(注意要判读两个数是否一样)。

附上Matrix67的miller-rabin算法介绍,(我整篇文章其实在关注的是Matrix67的素妹子,原来早在很久以前就存在虐狗行为了。我的miller-rabin的a只取了2和3,结果没有卡。这题感觉细节特别恶心,而且最后还需要高精度!

感觉给main函数炸掉了TAT。查看代码


6.22

####BZOJ 2083: [Poi2010]Intelligence test

一开始用的方法是利用st表的方法,记录后面$2^k$个和自己一样的数字的位置,再倍增找。BZOJ上莫名T掉,交到main上爆内存。看hzwer的题解觉得自己傻逼了,可以为每个数字开一个数组,记录这个数字出现的位置,之后二分即可。

####BZOJ 2084: [Poi2010]Antisymmetry

manacher改变一下即可。不过注意这个需要对于不是’*‘(分隔符)的位置直接跳过不处理。因为如果某个不是分割符号为中心作为“可以覆盖到最远回文串”,则会导致复制过来的len出错,中心字符是无法“对称”的。

####BZOJ 2085: [Poi2010]Hamsters

看到数据后突然有些似成相识,我是不是在哪里做过这题@cstdio。

可以预处理出来一张图,对于$i->j$的长度为$len(str_j) – i,j重合的长度$。之后$f_{i,j,k}$表示$i$到$j$走$k$条边的最短路,直接dp显然不行,可以发现这个是“符合结合律”的dp,直接倍增。

####BZOJ 2086: [Poi2010]Blocks

数据范围显然要求做到一次询问在$O(n)$完成。对于每个询问,处理一个sum数组,其中sum[i] = sum[i-1] + a[i] - K。接着对sum数组处理一个单调递减序列。之后从后往前,尝试求每个位置作为子序列结尾的最长长度。显然满足一段序列$[l,r]$符合条件的要求是$sum_r – sum_l \ge 0$。如果处理的过程中某个位置的sum值比之前(后面)某个值还要小,那么显然不可能成为答案。这样选择作为左端点的点在单调队列中的位置是只会向左移动的,用个指针维护左端点在单调队列中的位置即可。

查看代码


6.25

####BZOJ 2087: [Poi2010]Sheep

对着别人代码抄的,不过比想象中简单。预处理出每条边是否可行,即是否把分成两部分都是偶数。只关心是不是偶数就行了,这样一定是合法的。之后是一个dp,用$f_{i,j}$表示从第$i$个点到第$j$个点连线时构成的方案数,答案为$f_{1,n}$,转移方程如果$i$到$j$的连边合法,那么$f_{i,j} = sum_k f_{i,k}*f_{k,j}$,否则为0。

查看代码


6.26

####BZOJ 2088: [Poi2010]Teleportation

1到2的距离必须大于等于5,那么先假设最后求出来正确答案了,之后再做出来分层图,而且可以得结论:

  1. 如果最后答案1和2号点不连通,那么结果一定是1属于一个完全图中,2属于一个完全图中。
  2. 如果连通的话,那么层数一定等于6,更少的话不符合题意,更多的话可以合并一些层获得更优解。
  3. 如果连通的话,第一层和第六层一定只有一个点,分别是1和2,否则的话可以把第一层和第六层的点分到二、五层,解不会更差。
  4. 如果连通的话,那么第二层和第五层只会存在“在初始图中与1,2相邻的点”,否则可以把他们分给第三、四层,解不会更差。(1或2不存在邻接点时候显然直接按第1中情况算不会更差)
  5. 如果连通的话,继续按照结论3、4的思路,其实可以发现距离1为0,1,2的点一定在一、二、三层;距离2位0,1,2的点一定在六、五、四层中。剩下的点一定可以构造选在三、四层中,而且解不会更差。那么剩下如果二层点比五层的点多,那么放三层更优,反之放在五层最优。

之后统计答案就行,然后我讨论了这么多,代码似乎比别人长一些。不过1A,爽!

查看代码

####BZOJ 2091: [Poi2010]The Minima Game

先排序,之后记$f_i$表示第$i$个数以及之前的一个子局面的最优值。可以发现一个人如果选择的话一定选择后一段。可以反正其正确性:如果有空隙的话,后手可以补上,而且获得的分一定不低于先手,此时先手可以还获得剩余局面的最优分,但其实一开始可以直接选择获得剩余局面最优分的方案,再给后面一段带上去,这样一定不会更差。

之后dp方程为$f_i = max(f_{i-1}, a_i – f_{i-1})$,相当于枚举这个点属于新的一段或者归上一段。

查看代码

感觉poi2010剩下的题要不然不想做要不然就是太神,不太想玩了,弃坑弃坑,以后有机会慢慢玩。

有个妹子告诉我要早睡注意身体,激动了好长时间

CF Round 309 Div2

趁fst前先更blog

####A. Kyoya and Photobooks

题意:给你一个字符串,长度小于等于20。问在字符串中任意一个位置插入一个字母,有多少种字符串。

随便搞一下就行。

####B. Ohana Cleans Up

题意:给一个01矩阵,每次可以把一整列取反,可以操作任意次,问有最多几行完全为0。

显然操作影响所有行,如果一行变为全0那么只有和这行一样的才可以全0。

####C. Kyoya and Colored Balls

题意:有$k$个数字,数字$i$有$num_i$个,一个合法的排列要求最后一个数字$i$的位置一定比最后一个数字$i+1$的位置靠前。

求出来总共和为$n$,可以发现最后一个位置一定是$k$,然后把剩下$num_k – 1$扔到剩余$n-1$个位置,接着求$k-1$的答案填补进去。所以方案数为$f(k,n) = C(n-1, num_k-1) * f(k-1, n-num_k)$。

####D. Kyoya and Permutation

题意:给一个1至n的排列,求出其置换表示法,接着去掉括号,如果!@%$@$#&…细节太多自己去看原题。

理解错题意了,不知道是不是div1不发通知只有div2发。可以发现符合条件的序列第$i$个位置为$i$或者与$i+1$交换,最多交换一次。递推式发现是fibonacci数列,可以类似二分的从前往后构造下去就行了。

####E. Love Triangles

题意:有$n$个节点的图,任意两点有边,边的颜色可以使红色或者黑色。一些边的颜色已经给定。求满足:任意3个点构成的三角形只有1边是红色或者3条边都是红色。

看上去挺厉害,感觉自己计数题自己有点傻逼,就在那里想啊想,然后发现还是不会统计。剩15分钟的时候突然卧槽,发现自己傻逼了。

可以发现如果已知一个点与剩下所有点之间边的颜色,那么图是确定的,所以不妨记每个点颜色为与1点的边的颜色。

对于一条红边可以确定两个点颜色一定一样,对于一条黑边可以确定两个点颜色一定不一样。先用并查集把第一个连通块缩点,接着对于一条黑边在表示两个连通块之间点连边。记连通块个数为$cnt$。二分图染色,看看是否合法,如果不合法答案为0。合法的的话一个连通块颜色有两种,但是1号点所在连通块颜色固定(其实是没有颜色),所以答案为$2^{cnt-1}$。

我再讲一个有趣的故事,写完代码后发现比赛结束1分钟了→_→。