bzoj

BZOJ 1111: [POI2007]四进制的天平Wag

妖精的绣舞 提交于 2020-02-07 19:40:58
SB题。 很容易想到先二话不说把十进制转四进制,然后我们考虑DP: 设 \(f_{i}\) 表示从高位到低位的第 \(i\) 位填成目标状态的最小步数/方案数 设 \(g_{i}\) 表示从高位到低位的第 \(i\) 位填成目标状态 \(+1\) 的最小步数/方案数(因为涉及到向下一位退位) 那么我们容易得到以下转移: \[ f_i\leftarrow f_{i-1}+num_i\\f_i\leftarrow g_{i-1}+4-num_i\\g_i\leftarrow f_{i-1}+num_i+1\\g_i\leftarrow g_{i-1}+3-num_i\\ \] 然后就做完了233 #include<cstdio> #include<cstring> #include<algorithm> #define RI register int #define CI const int& using namespace std; const int N=3005,mod=1e9; struct data { int x,y; inline data(CI X=1e9,CI Y=0) { x=X; y=Y; } friend inline data operator + (const data& A,CI x) { return data(A.x+x,A.y); } }f[N],g

[bzoj 4543] Hotel加强版

我的未来我决定 提交于 2020-02-06 17:01:09
题意 给定一棵有n个点的树,有三元组$(a,b,c)$满足a,b,c两两距离相等,求这样的三元组的个数。 n<=100000 题解 初步思考 这种题目有个经典解法就是固定两点求中点。但很遗憾这种做法是$O(n^2)$的。 所以我们用树形dp解决这个问题。 考虑从三点lca处统计贡献,这样比较方便。 状态设计 我们考虑逐步满足法,先统计一个点,再用一个点的数据计算两个点都满足的数据,再用一个点和两个点的数据计算三个点都满足的数据。 于是,我们用$f[i][j]$表示在i的子树内与i距离为j的点的个数, 用$g[i][j]$表示在i的子树内有两个点,且他们再加上一个i子树外的与i距离为j的点就满足题目要求。 之所以这样设置是为了方便将g和f拼在一起,且不重不漏地统计答案。 转移方程 那么怎样转移计算g[i][j]的值呢? 因为第二项是j,由定义得现在还需要一条长度为j的边。 考虑一个个枚举i的儿子,统计贡献。 第一种情况,这两条边,一条在已经枚举过的儿子里找,一条在新加进来的找。 那么i就是这两条边的交点,可得两条边长度为i. 下图中,红色表示现在连接的边,黄色表示需要的边,绿色表示将要配对成一个三元组的边。 这种情况可以用$f[i][j]*f[son][j-1]$描述,其中son表示新加进来的儿子。 另外一种情况,两条边都在son里找。 那么就是在son原有的二元组的基础上再加上i-

BZOJ 4555: [Tjoi2016&Heoi2016]求和

无人久伴 提交于 2020-02-04 23:22:55
好久之前做的题了,算是我的 NTT 入门题了,然后我点开题单里的多项式,除了这题全TM是权限题 当场去世 废话不多说直接推式子: \[ ans=\sum_{i=0}^n\sum_{j=0}^i \left\{_j^i\right\}\times 2^j\times j!\\=\sum_{i=0}^n\sum_{j=0}^n \left\{_j^i\right\}\times 2^j\times j!\\=\sum_{j=0}^n 2^j\times j!\times \sum_{i=0}^n\left\{_j^i\right\}\\=\sum_{j=0}^n 2^j\times j!\times \sum_{i=0}^n\sum_{k=0}^j (-1)^k\times \frac{1}{k!(j-k)!}\times (j-k)^i\\=\sum_{j=0}^n 2^j\times j!\times \sum_{k=0}^j (-1)^k\times \frac{1}{k!(j-k)!}\times \sum_{i=0}^n(j-k)^i\\=\sum_{j=0}^n 2^j\times j!\times \sum_{k=0}^j \frac{(-1)^k}{k!}\times \frac{\sum_{i=0}^n(j-k)^i}{j-k}\\ \] 注意上面的 \(\left\

BZOJ 1485: [HNOI2009]有趣的数列

耗尽温柔 提交于 2020-02-04 03:03:57
都是数学题 思维最重要,什么什么数都没用,DP直接乱搞(雾.. 参考LH课件,以及资料:http://daybreakcx.is-programmer.com/posts/17315.html 做到有关的题目会更新 n个乒乓球放到m个盒子里的方案数 1.球相同,盒子不同,不允许空 分成m段,n-1个空选m-1个放隔板 ,$\binom{n-1}{m-1}$ 2.球相同,盒子不同,允许空 $(1)$ 加入m个球变成不允许空 $(2)$ m-1个隔板和球放在一起,从中选m-1个做隔板 $C_{n+m-1}^{m-1}$ 3.球相同,盒子相同,不允许空 就是整数划分问题啊...n个数写成m个数的和的形式的方案数 $ f[i][j]=f[i-1][j-1]+f[i-j][j] $ 有1的话就是$ f[i-1][j-1]$,没有1的话就拿出j个1先放上再分剩下的,$f[i-j][j]$ 或者直接写暴力转移然后化简 4.球相同,盒子相同,允许空 $ \sum_{j=1}^mf[n][j] $ 5.球不同,盒子相同,不允许空 第二类 Stirling 数:n个不同的元素分成m个集合的方案数 $ S(i,j)=S(i-1,j-1)+S(i-1,j)*j $ $ S(n,n)=1 \quad n \ge 0\quad,\quad S(n,0)=0 , n\ge 1$

BZOJ 4555: [Tjoi2016&Heoi2016]求和 (NTT + 第二类斯特林数)

十年热恋 提交于 2020-02-04 02:26:12
题意 给你一个数 \(n\) 求这样一个函数的值 : \[\displaystyle f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i} {i \brace j} 2^j j!\] \((1 \le n \le 100000)\) 题解 这个题直接划式子 然后 \(NTT\) 就行了qwq 需要知道一个容斥求斯特林数的东西 \[\displaystyle \begin{Bmatrix} n \\ m \end{Bmatrix} = \frac{1}{m!} \sum_{k=0}^m (-1)^k (m-k)^n\] 这个用组合意义去理解 我们考虑把 \(n\) 个物品放进 \(m\) 个盒子里中的方案数就是斯特林数(盒子不区分) 然后我们考虑枚举至少有 \(k\) 个空的盒子的方案数 那么 \(n\) 就可以随便放入剩下的 \((m-k)\) 个盒子中去 这个式子我们划一下 就可以得到一个用来 \(NTT\) 的式子... 拆一下组合数.... \[\displaystyle \begin{Bmatrix} n \\ m \end{Bmatrix} = \frac{1}{m!} \sum _{k=0}^{m} (-1)^k \frac{m!}{k!(m-k)!}(m-k)^n\] 然后再简单整理一下qwq \[\displaystyle \begin{Bmatrix

BZOJ 4652. [Noi2016] 循环之美

谁说胖子不能爱 提交于 2020-02-02 19:44:39
首先,一个分数 $\frac{p}{q}$ 在 $k$ 进制下是纯循环小数,就是 $\exists t$,$p \equiv p \times k^t \pmod q$,其中 $p \bot q$,那么即为 $k^t \equiv 1 \pmod q$,要存在解,就得 $k \bot q$。 所以答案就是 $\sum_{i=1}^n\sum_{j=1}^m [i\bot j][k\bot q]$ $$\sum_{i=1}^n\sum_{j=1}^m [i\bot j][k\bot j]$$ $$=\sum_{i=1}^n\sum_{j=1}^m[k\bot j]\sum_{d|(i,j)}\mu(d)$$ $$=\sum_{d=1}^{\min\{n,m\}}[d\bot k]\mu(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[j\bot k]$$ $$=\sum_{d=1}^{\min\{n,m\}}[d\bot k]\mu(d)\lfloor\frac{n}{d}\rfloor s(\lfloor\frac{m}{d}\rfloor)$$ 其中 $s(n)=\sum_{i=1}^{n}[i\bot k]=\lfloor\frac{n}{k}\rfloor s(k)

[BZOJ 1086][SCOI 2005] 王室联邦

空扰寡人 提交于 2020-02-01 17:59:49
题目大意 一个 (n) 个节点的树,将点划分为若干块,每块的大小最少为 (b) ,最大为 (3b) 。同时,为每一块选一个节点,使得块中所有节点到这个特殊节点的路径上的点(特殊节点本身除外)均在这一块内。给定树,输出任意一种划分方案(可能无解)。 (1 leqslant n leqslant 1,000, 1 leqslant b leqslant n) 题目链接 BZOJ 1086 CodeVS 2450 题解 当且仅当 (b > n) 时无解。有解时,对树进行 dfs,每当某一点的一些子树大小超过了 (b) ,就分成一块,并令该点为新分的块的特殊节点。dfs 后,可能会剩一些节点没有块,再 dfs 一遍划给旁边的块就行了。 代码 一开始交的代码没有特判无解,居然就 AC 了。。。 那堆 DBG 是因为一开始把 stack 写成了 queue 。。。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 #include <stack>const int MAXN = 1005;struct ;struct Node { Edge

BZOJ 5324: [Jxoi2018]守卫 区间DP

眉间皱痕 提交于 2020-02-01 15:39:16
思路非常巧妙啊 code: #include <cstdio> #include <algorithm> #define ll long long #define N 5003 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int f[N][N],h[N],n; double slope(int l,int r){return (double)(h[r]-h[l])/(r-l);} bool cansee(int l,int x,int r){return slope(x,r)>slope(l,r);} int main() { // setIO("input"); int i,j,ans=0; scanf("%d",&n); for(i=1;i<=n;++i) scanf("%d",&h[i]); for(int r=1;r<=n;++r) { f[r][r]=1; ans^=f[r][r]; int sum=1,p=0; for(int l=r-1;l>=1;--l) { if(!p||cansee(l,p,r)) { sum+=min(f[l+1][p-1],f[l+1][p]); p=l; } f[l][r]=sum+min(f[l][p],f[l][p-1]); ans^=f[l][r];

BZOJ 2342: [Shoi2011]双倍回文

南楼画角 提交于 2020-02-01 12:21:39
Description Input 输入分为两行,第一行为一个整数 ,表示字符串的长度,第二行有 个连续的小写的英文字符,表示字符串的内容。 Output 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出 0 。 Sample Input 16 ggabaabaabaaball Sample Output 12 HINT N<=500000 显然 这一题比较水如果会回文自动机的话 然后就成为回文自动机模版题了 先建出回文自动机 然后建出fail树对长度为偶数的fail树dfs 如果一个节点的长度%4==0并且这个节点长度的一半是这个节点的fail 然后就输出就好了 Manacher的话就不会了 果然还是太弱了。。。 code: #define MAXN 505005 #define maxn 26 #include <stdio.h> #include <cstring> #include <algorithm> #include <iostream> using namespace std; int n,e=1,first[MAXN],vis[MAXN],Ans; char s[MAXN]; struct edge{ int u,v,next; }a[MAXN<<1]; inline void push(int u,int v){ a

bzoj 2342: [Shoi2011]双倍回文

房东的猫 提交于 2020-02-01 12:20:48
Description Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。 Output 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出 0 。 Sample Input 16 ggabaabaabaaball Sample Output 12 HINT N<=500000 Source 第二道回文自动机的题了... 这道题就是找沿着fail找到能找到一个点使len[u]==2*len[u]&&len[u]%4==0; 按fail连边之后,在fail树上dfs即可(可以对len开一个桶) #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> using namespace std; typedef long long ll; const int N=600050; int gi() { int x=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch