bzoj

LG4980 【模板】Polya定理 和 BZOJ2026 宝石纪念币

若如初见. 提交于 2020-01-08 23:20:55
题意 题目描述 给定一个$n$个点,$n$条边的环,有$n$种颜色,给每个顶点染色,问有多少种 本质不同 的染色方案,答案对$10^9+7$取模 注意本题的本质不同,定义为: 只需要不能通过旋转与别的染色方案相同 。 输入输出格式 输入格式: 第一行输入一个$t$,表示有$t$组数据 第二行开始,一共$t$行,每行一个整数$n$,意思如题所示。 输出格式: 共$t$行,每行一个数字,表示染色方案数对$10^9+7$取模后的结果 输入输出样例 输入样例#1: 复制 5 1 2 3 4 5 输出样例#1: 复制 1 3 11 70 629 说明 $$n \leq 10^9$$ $$t \leq 10^3$$ 分析 先找不动点个数公式。考虑循环移动 \(i\) 位这个置换,把珠子循环编号。由于移动后编号要重复,所以最大的编号一定是 \(\textrm{lcm}(i,m)\) 。所以一个循环里面的珠子个数就是 \(\frac{\textrm{lcm}(i,m)}{i}=\frac{n}{\gcd(i,n)}\) 。所以共有 \(\gcd(i,n)\) 个循环。因此不动点个数是 \(n^{\gcd(i,n)}\) 所以答案式为 \[ \frac 1n\sum_{i=0}^{n-1}n^{\gcd(i,n)} \\ =\frac 1n\sum_{d|n}\varphi(\frac nd)n^d

BZOJ 1495: [NOI2006]网络收费 树形DP+复杂度分析

痴心易碎 提交于 2020-01-07 06:36:28
code: #include <cstdio> #include <cstring> #include <algorithm> #define ls x<<1 #define rs x<<1|1 #define N 2105 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n; ll ans; int tp[N],B[20],s[20]; ll cost[N][12],f[N][N],C[N][2]; int lca(int x,int y) { int i; for(i=n-1;i>=0;--i) if((x>>i)!=(y>>i)) break; return n-i-1; } void dfs(int x,int dep) { if(dep==n) { f[x][0]=C[x-B[n]][0]; f[x][1]=C[x-B[n]][1]; for(int i=0;i<dep;++i) f[x][s[i]^1]+=cost[x-B[n]][i]; return; } s[dep]=0; memset(f[x],0x3f,sizeof(f[x][0])*(B[n-dep]+1)); dfs(ls,dep+1),dfs(rs,dep+1); for

BZOJ 2286 [Sdoi2011]消耗战 (虚树模板题)

邮差的信 提交于 2020-01-07 06:10:32
题意 有 \(n\) 个点形成一棵树,边有权值。 \(m\) 次询问,每次询问,给出 \(k\) 个关键点,问把这些关键点都与 \(1\) 号节点断开(不连通)的最小断边的权值和。保证 \(1\) 号节点不是关键点。 \(n,m\le 250000,\sum k\le500000\) 题解 考虑只有一次询问怎么做。 直接树形 \(dp\) 就行了。用 \(dp[u]\) 表示把 \(u\) 这棵子树断开的最小代价。对于关键点必须断 \(u\) 到父亲的边。否则要么断当前点到根的路径上边权最小值,要么断子树内的边(代价为:子树内有关键点的儿子的 \(dp\) 值之和)。 我们可以把 \(1\) 号根节点到父亲的边权设为 \(+\infty\) ,那么 \(dp[1]\) 就是答案。 然后考虑多组数据,发现 \(\sum k\le 500000\) ,显然每次我们需要 \(O(k)/O(k\log k)\) 的算法。 那么就只需要建虚树 \(DP\) 就完事了,每次 \(O(k\log k+k)\) 。这道题还有一个性质,就是虚树中关键点子树中的关键点可忽略。建虚树的时候没有必要建出来。 CODE #include <cstdio> #include <vector> #include <cctype> #include <cstring> #include <algorithm>

BZOJ 2653 middle 二分答案+可持久化线段树

夙愿已清 提交于 2020-01-02 12:08:26
  题目大意:有一个序列,包含多次询问。询问区间左右端点在规定区间里移动所得到的最大中位数的值。   考虑对于每个询问,如何得到最优区间?枚举显然是超时的,只能考虑二分。   中位数的定义是在一个序列中,比中位数小的数跟比它大的数一样多,由于我们要求的是最大的中位数,自然希望能找到一个区间,使得该区间内比该中位数大的数尽量多。   二分中位数k,假设比k小的数记为-1,其余的数记为1,那么我们就是要寻找最大连续子序列和,若找到的最大的和>=0,则当前的k就是合法的。   最大连续子序列和可以用线段树来维护,由于存在多组询问,每次建一棵线段树很慢,我们选择建主席树。初始时,把数按从小到大排好序,全部的数记为1,做到第i个数时,将第i-1个数记为-1,以此做下去。   那么这样最终二分到的答案会不会不在指定的区间范围之中呢?   肯定是不存在的,我们可以分类讨论。    n为偶数:n = 4时,0 1 2 3,中位数的位置为2,如果答案在1-2之间,则会有更优的答案;如果在2-3之间,显然是不可能的。    n为奇数:n = 3时,0 1 2 3 4,中位数的位置为2,分析同上。 #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; typedef long long LL;

BZOJ 刷题总结(持续更新)

自闭症网瘾萝莉.ら 提交于 2020-01-02 04:55:26
本篇博客按照题号排序(带*为推荐题目) 1008 [HNOI2008]越狱 很经典的题了。。龟速乘,龟速幂裸题,, 1010 [HNOI2008]玩具装箱toy* 斜率优化 基本算是裸题。 1012 最大数 单调队列/单调栈 随便搞一搞就好 (水题。。。) 1045 糖果传递(双倍经验请做 3293 分金币) 贪心+中位数 排序后搞一搞可过。。(水题。。。) 1051 受欢迎的牛* tarjan (提高T1+ -- T2难度) 1106: [POI2007]立方体大作战tet* 树状数组+贪心 1191 [HNOI2006]超级英雄Hero* 二分图匹配裸题 匈牙利可过 将每个题向他们所对应的妙计连条边 这样的话,一边是题目,一边是妙计,跑匈牙利即可。 1230 [Usaco2008 Nov]lites 开关灯 线段树裸题 1258 [CQOI2007]三角形tri* 找规律 一个三角形最多周围有三个三角形连着。 然后如果末尾是4,则与它相邻的是该组的1,2,3。如果末尾是1/2/3,与他们相邻的一定是各种4......,而且第一个一定是同组的4,然后剩下的找找规律就好了。。 1259 [CQOI2007]矩形rect 吐槽一下当年的重庆市选。。怎么连着出打表+找规律呢。。 这个题。。网上说插头DP。。可我只会打表。如何打,网上有。。。 1260: [CQOI2007

【BZOJ】1119: [POI2009]SLO

牧云@^-^@ 提交于 2020-01-01 03:52:04
题意 长度为 \(n(1 \le n \le 1000000)\) 的账单, \(+\) 表示存1, \(-\) 表示取1,任意时刻存款不会为负。初始有 \(p\) ,最终有 \(q\) 。每一次可以耗时 \(x\) 将某位取反,耗时 \(y\) 将最后一个移到最前面,求最小耗时使得账单正确。 分析 首先很显然最终 \(+\) 和 \(-\) 的数目是可以确定的。 所以我们把账单按照每一个开头扫一遍就行了。 题解 将账单拓展成 \(2n\) ,然后从 \(2\) 扫到 \(n+1\) ,求以这个开头的最小费用。 对于 \(i\) 开头的,我们只需要在 \(i\) 到 \(i+n-1\) 的账单修改成数目正确的 \(+\) 和数目正确的 \(-\) 即可。怎么修改呢?目前我们只需要保证不会出现负数即可。也就是前缀和中没有负数。所以我们找到第一个前缀和最小的位置 \(j\) 。如果 \(s_j\) 小于0,则表示在 \(i\) 到 \(j\) 需要将 \(\left \lceil \frac{-s_j}{2} \right \rceil\) 个负的改成正的。然后再根据 \(+\) 和 \(-\) 的最终个数和当前个数计算一下费用即可。 求一个区间的最小值可以用单调队列,所以复杂度 \(O(n)\) #include <bits/stdc++.h> using namespace std

BZOJ 1119: [POI2009]SLO [置换群]

时间秒杀一切 提交于 2020-01-01 03:51:48
传送门: 现在$POI$上的题洛谷都有了,还要$BZOJ$干什么 和$cow\ sorting$一样,只不过问$a_i \rightarrow b_i$ 注意置换是位置而不是数值...也就是说要$i$的数值$a_i$要变到$b$中数值$a_i$的位置 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=1e6+5; typedef long long ll; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,a[N],pos[N],w[N],f[N],Min=N; ll ans; bool vis[N]; int main(){ freopen("in","r",stdin); n=read(); for(int i=1;i<=n;i++) w[i]=read(),Min=min(Min,w[i]); for

BZOJ 3994 约数个数和

雨燕双飞 提交于 2019-12-26 04:48:13
Description 设 \(d(x)\) 为 \(x\) 的约数个数,给定 \(N,M\) ,求 \[\sum_{i=1}^{N}\sum_{j=1}^{M}d(ij)\] 。 Input 输入文件包含多组测试数据。 第一行,一个整数 \(T\) ,表示测试数据的组数。 接下来的 \(T\) 行,每行两个整数 \(N,M\) 。 Output \(T\) 行,每行一个整数,表示你所求的答案。 Sample Input 2 7 4 5 6 Sample Output 110 121 HINT \(1 \le N, M \le 50000\) \(1 \le T \le 50000\) 这题有个很屌的结论: \[\sum_{i=1}^{N}\sum_{j=1}^{M}d(ij)=\sum_{i=1}^{N}\sum_{j=1}^{M}\lfloor\frac{N}{i}\rfloor\lfloor\frac{M}{j}\rfloor\lbrack gcd(i,j)=1 \rbrack\] 根据 PoPoQQQ博客 所说的,我们可以先证明这个式子的成立: \[d(nm)=\sum_{i \mid n}\sum_{j \mid m}\lbrack gcd(i,j)=1 \rbrack\] 我们可以证明一下:我们对每个质数 \(p\) 单独算贡献,设 \(n=n’ \times p^{k

bzoj 3328 PYXFIB——单位根反演

落花浮王杯 提交于 2019-12-26 01:33:18
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=3328 单位根反演主要就是有 \( [k|n] = \frac{1}{k}\sum\limits_{i=0}^{k-1}w_{k}^{i*n} \) 如果 k | n ,转 n 下就会是 1 ;不然用等比数列求和公式可知是 0 。 一般是构造一个 \( f(x) = ( 1+x )^n \) 之类的,来求含有组合数的式子。比如              \( \sum\limits_{i=0}^{n}C_{n}^{i*k} = \sum\limits_{i=0}^{n}C_{n}^{i}[ i | k ] \)                \( = \frac{1}{k}\sum\limits_{i=0}^{n}C_{n}^{i}\sum\limits_{j=0}^{k-1}w_{k}^{j*i} \)                \( = \frac{1}{k}\sum\limits_{j=0}^{k-1}\sum\limits_{i=0}^{n}C_{n}^{i}w_{k}^{j*i} \)                \( = \frac{1}{k}\sum\limits_{j=0}^{k-1}(1+w_{k}^{j})^n \) 所以设 \( f(x) = (

BZOJ 3451: Tyvj1953 Normal 点分治+FFT

此生再无相见时 提交于 2019-12-25 22:46:33
根据期望的线性性,我们算出每个点期望被计算次数,然后进行累加. 考虑点 $x$ 对点 $y$ 产生了贡献,那么说明 $(x,y)$ 之间的点中 $x$ 是第一个被删除的. 这个期望就是 $\frac{1}{dis(x,y)+1}$,所以我们只需求 $\sum_{i=1}^{n}\sum_{j=1}^{n}\frac{1}{dis(i,j)+1}$ 即可. 然后这个直接求是求不出来的,所以需要用点分治+FFT来算树上每种距离都出现了多少次. code: #include <bits/stdc++.h> using namespace std; #define N 500003 #define ll long long #define setIO(s) freopen(s".in","r",stdin) const double pi=acos(-1); ll ans[N]; int edges,root,sn,n,mxdep; int size[N],mx[N],hd[N],to[N<<1],nex[N<<1],vis[N]; inline void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } struct cpx { double x,y; cpx(double a=0,double b=0) {