bzoj

bzoj 2741: 【FOTILE模拟赛】L(可持久化trie + 分块优化)

时光毁灭记忆、已成空白 提交于 2020-02-01 03:25:12
预处理 a a a 数组的前缀和,问题就变成在[l - 1,r] 区间内找任意两个数,使得异或值尽可能大。 用可持久化 trie 暴力做 复杂度是 O ( 32 ∗ n ∗ m ) O(32 * n * m) O ( 3 2 ∗ n ∗ m ) 即使去掉 32 这个系数,也可能会被卡常,考虑如何优化。 考虑预处理一部分区间的答案,令 f [ l ] [ r ] f[l][r] f [ l ] [ r ] 表示 区间 [ l , r ] [l,r] [ l , r ] 的答案,显然不能预处理全部的区间,考虑分块预处理:对 l 分块(或者对 r 分块),f[l][r] 表示 从第 l 个 块的起点到 r 这段区间内 与 a[r] 异或的最大值。g[l][r] 表示 从第 l 个 块的起点到 r 这段区间内的答案。 通过 f[l][r] 和 g[l][r - 1] 可以得到 g[l][r],因此可以边搞边处理。 对于每一次询问[l,r],找到 l 所在块号的右边界 e d ed e d ,对于 [ed + 1,r] 的答案已经预处理过,枚举 [l,ed] 每一个点,在可持久化 trie 上查询 区间 [l + 1,r] 与 a[l] 异或可得到的最大值,[ed + 1,r]的答案合并即得到[l,r] 的答案。 复杂度: O ( 30 ∗ n n + 30 ∗ m ∗ n ) O(30*n

BZOJ 第二页 除草

北战南征 提交于 2020-01-31 05:24:30
第二页的题跟第一页不是一个档次的啊…………花了两周的时间把第二页做了一做………………各种神题虐人啊………………我就只写我看了、写了或者有思路的吧……………… 1100:第一道就是神题,因为是要求对称轴所以弄一堆叉积距离来做kmp找个数,跑得还挺快,rank1 1101:数论题,莫比乌斯函数搞一搞 1102:裸的bfs 1103:树状数组+dfs序 1104:由于要尽量放较矮的,并且高度总数不多,所以按高度从低往高进行扩展,并且用两个队列维护分别进行扩展,又是rank1 1105:证明一下所有点都在x=y的同一侧一定是最优的,然后分情况算一下就行了 1106:MS是树状数组怎么维护一下,做这道题比较早了,记不得了 1107:没做,但是似乎是可以用线段树维护乱搞 1108:神级水题 1109:一个比较难想的DP,可以去看seter博客 1110:利用倍数关系做进制划分后贪心 1111:水DP 1112:平衡树维护中位数 1113:一种神奇的贪心方式 1115:简单的博弈题 1116:窘迫的题意,双向边不算入度出度的……并查集维护每个联通块内点和边的个数,讨论一下即可 1117:又是神题,又是神一般的贪心 1119:找出置换群和分两种情况算答案 1121:神级水题 1122:倒着枚举移了多少次后每次维护一个最小前缀和维护答案 1123:连通分量水题,rank1 1124:血腥的题面…

[BZOJ 4173]数学

孤人 提交于 2020-01-30 03:24:59
一、题目 二 、解法 又到了欢乐推式子时间,先推那个判断式(本文所有除法均为整除): m % k + n % k ≥ k m\%k+n\%k\geq k m % k + n % k ≥ k m − m k k + n − n k k ≥ k m-\frac{m}{k}k+n-\frac{n}{k}k\geq k m − k m ​ k + n − k n ​ k ≥ k n + m k − m k − n k ≥ 1 \frac{n+m}{k}-\frac{m}{k}-\frac{n}{k}\geq1 k n + m ​ − k m ​ − k n ​ ≥ 1 由于 0 ≤ n + m k − m k − n k ≤ 1 0\leq\frac{n+m}{k}-\frac{m}{k}-\frac{n}{k}\leq1 0 ≤ k n + m ​ − k m ​ − k n ​ ≤ 1 ,所以可以直接把上面的值当成判断式来用,也就是说,我们现在要求这东西: ϕ ( n ) ϕ ( m ) ∑ k = 1 n + m ( n + m k − m k − n k ) ϕ ( k ) \phi(n)\phi(m)\sum_{k=1}^{n+m}(\frac{n+m}{k}-\frac{m}{k}-\frac{n}{k})\phi(k) ϕ ( n ) ϕ ( m ) k = 1 ∑ n +

BZOJ 4416: [Shoi2013]阶乘字符串

假如想象 提交于 2020-01-29 21:29:11
简单的 状压DP ,而且很困惑为什么大家都不知道判无解的原因? 首先有一个结论,当 \(n>21\) 时无解,证明如下(个人口胡不保证正确性): 考虑当我们的字符串是这样构造时:一个 \(n\) 个字符的排列+一个 \(n\) 个字符的排列+……+一个 \(n\) 个字符的排列(共计 \(n\) 个),此时显然是有解的 再手玩一下容易发现这个条件 不仅充分而且必要 ,如果有一段中间有字符缺失那么必然会导致某个排列无法表示出来 那么很显然最优的表示方案就是类似分块的根号级别的分组,由 \(\sqrt{450}=21.2\cdots\) ,因此超过 \(21\) 无解 剩下的非常简单了,排列化为子集,设 \(f_{s}\) 表示集合 \(s\) (状压)内的字符都满足要求是右端点至少到那里 转移考虑分别讨论 \(s\) 的最后一个字符是什么,那么: \[f_s=\max\{ g_{f_{s\cap C_s c},c}|c\in s\}\] 其中 \(g_{i,j}\) 表示在位置 \(i\) 之后(不包含)第一个 \(j\) 的位置,取 \(\max\) 是因为对于任意一个字符都要满足 最后判断一下 \(f_{\text{全集}}\) 与 \(len\) 的关系即可 #include<cstdio> #include<cstring> #include<iostream>

BZOJ 4766 文艺计算姬

╄→尐↘猪︶ㄣ 提交于 2020-01-29 17:36:54
Link 考虑Prufer序列,最后剩下两个没删节点之间是有边相连的,所以一定位于二分图的两侧。 因为我们每次是删掉一个点然后将其连着的点加入Prufer序列,所以Prufer序列一定是 \(n-1\) 个右侧点和 \(m-1\) 个左侧点。 稍微模拟一下可以发现,当我们选定了Prufer序列中出现了哪些点之后,这棵生成树就已经完全确定了,换言之Prufer序列就只有一种排列方案。 因此总的方案是 \(n^{m-1}m^{n-1}\) 。 #include<cstdio> typedef long long i64; i64 n,m,p; i64 inc(i64 a,i64 b){return (a+b)%p;} i64 mul(i64 a,i64 k){i64 r=0;for(;k;k>>=1,a=inc(a,a))if(k&1)r=inc(a,r);return r;} i64 pow(i64 a,i64 k){i64 r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;} int main(){scanf("%lld%lld%lld",&n,&m,&p),printf("%lld",mul(pow(n,m-1),pow(m,n-1)));} 来源: https://www.cnblogs.com

BZOJ 2159: Crash 的文明世界

只愿长相守 提交于 2020-01-29 17:05:02
记得去年暑假集训的时候本来想了一个 动态点分 的做法的,然后写道一半因为某些不知名原因就没写了,然后就一直放着,然后发现 斯特林反演 真NM好写 首先考虑用关于幂的斯特林反演: \[m^n=\sum_{i=0}^m \left\{ ^n_i\right\}\times i!\times C_m^i\] 套上去就是: \[ans(x)=\sum_{i=1}^n dis(i,x)^k\] \[=\sum_{i=1}^n \sum_{j=0}^k \left\{ ^k_j\right\}\times C_{dis(i,x)}^j\times j!\] \[=\sum_{j=0}^k \left\{ ^k_j\right\}\times j!\times \sum_{i=1}^n C_{dis(i,x)}^j\] 显然我们现在只要知道 \(\sum_{i=1}^n C_{dis(i,x)}^j\) 怎么求即可,设: \[dn_{x,i}=\sum_{y\in x} C_{dis(x,y)}^i\] \[up_{x,i}=\sum_{y\not \in x} C_{dis(x,y)}^i\] 其中 \(y\in x\) 表示 \(y\) 在 \(x\) 子树内 显然我们可以推出关于 \(dn\) 的方程: \[dn_{x,i}=\sum_{y\in x} C_{dis(x,y)}^i\] \

BZOJ 5510: [Tjoi2019]唱、跳、rap和篮球 OGF+NTT

浪子不回头ぞ 提交于 2020-01-29 16:37:37
十分轻松的生成函数题. code: #include <cmath> #include <cstring> #include <algorithm> #include <cstdio> #include <string> #define ll long long #define ull unsigned long long using namespace std; namespace IO { char buf[100000],*p1,*p2; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() { int x=0; char s=nc(); while(s<'0') s=nc(); while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc(); return x; } void print(int x) {if(x>=10) print(x/10);putchar(x%10+'0');} void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); // freopen(out.c_str(),"w"

[BZOJ 2658]小蓝的好友

荒凉一梦 提交于 2020-01-28 13:46:50
一、题目 二、解法 正难则反,求至少包含一个黑格子就等于全部减去不包含黑格子的方案数。 考虑单调栈,对于每一行,求出每一个点最长上升,不碰到黑格子的距离,得到一个数组 u p up u p ,本题的一个重要条件是 数据随机 ,我们对 u p up u p 数组建立 t r e a p treap t r e a p ,其中下标作为减值, u p up u p 作为修正值,这样建出来的数满足根节点的 u p up u p 最小,而且由于 u p up u p 随机,能够保证复杂度是 log ⁡ \log lo g 。 考虑每个点的贡献,就是在 t r e a p treap t r e a p 中的: ( u p [ x ] − u p [ f a [ x ] ] ) × s i z e [ x ] × ( s i z e [ x ] + 1 ) ÷ 2 (up[x]-up[fa[x]])\times size[x]\times (size[x]+1)\div 2 ( u p [ x ] − u p [ f a [ x ] ] ) × s i z e [ x ] × ( s i z e [ x ] + 1 ) ÷ 2 ,求和即可。 怎么理解上式呢?请看下图: 就比如这样的一颗局部 t r e a p treap t r e a p ,我们的根通过上式处理了红色部分的贡献

BZOJ 1005. [HNOI2008]明明的烦恼

浪子不回头ぞ 提交于 2020-01-23 15:08:53
prufer序列为无根树的一种数列。长度为 $n - 2$ prufer转无根树 将最小编号的叶子删去,prufer序列加入其父亲。重复至树只剩下两个节点。 无根树转prufer 取出prufer首元素,与待选点集中最小未出现在prufer序列中的点连边,并将该点在待选点集中删去,直至待选点集剩下两个节点,将这两个节点连边。待选点集初始为 $1$ ~ $n$。 一个节点在prufer序列中出现次数为该节点度数减一。 判断无解的情况:出现度数为 $0$ 的点,在prufer序列中出现次数超过 $n$ - $2$。 有解情况下,设 $cnt$ 为有度数要求的节点个数,$sum = \sum_{i = 1} ^{cnt}(d_i - 1)$。 那么答案为 $C_{n-2}^{sum} \times \dfrac{sum!}{\prod_{i=1}^{cnt}(d_i-1)!} \times (n-cnt)^{n-2-sum}$ 化简得到$\dfrac{(n-2)!}{(n-sum-2)! \times \prod_{i=1}^{cnt}(d_i-1)!} \times (n-cnt)^{n-2-sum}$ #include <bits/stdc++.h> const int N = 1007; const int MOD = 10000; int num[N]; int prime[N]

bzoj 泛做

爱⌒轻易说出口 提交于 2020-01-22 23:47:10
3003 这个题是这样的,对序列差分后,每个取反操作就是给两个端点的值取反,然后背包之后再状压就好了 4128 这题棒棒的QAQBSGS 23333 4176 这个杜教筛呃呃呃 大爷链接 3028 我要去学学生成函数 大爷链接 4025 我真TM是智商爆降了,这个东西明显的按时间分治一下就好了,管他什么lct 3498 一位大爷:“将所有点分成两类:度数 < sqrt(m)的和度数 > sqrt(m)的.先求包含第一类点的三元环个数.由于边很少,所以枚举2条边即可.由于一个点的度不超过sqrt(m),所以一条边最多被枚到(sqrt(m))次,最多枚M条边,所以这个操作时O(m sqrt(m))的.再求不包含第一类点的三元环个数.由于每条边贡献2个度,所以二类点的数量是O(sqrt(m))级的.直接枚举三个点,复杂度O((sqrt(m))^3)=O(m sqrt(m))所以算法总的复杂度是O(m*sqrt(m))的.” 5043 先发个 神犇友链 当时只知道暴力,f[i][j]表示第i位剩余j最小的k但是这样j为2^60太大无法忍受,所以可以倒着按位做表示这一位剩余j,一定满足j<=n,这样复杂度降为60n,好棒棒呦 4241 一样看以为莫队结果被怼啦 大爷链接 ,填填坑 2400 这题其实很简单,然而......因为是异或运算,所以每一位独立然后就是最小割了(捂脸 4036