伤寒杂病论

持续更新 Gu~

大概是杂文集吧

以下是目录:

0. 集合

1. 光速幂(k 进制倍增)

a,p 一定,求

axmodp

1. 朴素

基本的欧拉降幂就不说了,可以将 x 缩小到 φ(p)p 的范围内 .

考虑分块预处理,令 r=p,则我们可以把 ax 分成几个整块的 ar 和一个散的

预处理 ar,(ar)2,(ar)3,,,(ar)ra,a2,ar,然后我们就可以求 ax

ax=arp+q=(ar)paq

这里 rp+q 类似一个带余除法,0q<r .

这样空间复杂度 O(p),时间复杂度 O(p)O(1)

这玩意还可以用类似方法搞搞扩域光速幂,矩阵光速幂啥的 .

Code:

template<int MOD>
struct FastPow
{
private:
	ll p1[66666],p2[66666];
	static ll qpow(ll a,ll n)
	{
		ll ans=1;
		while (n)
		{
			if (n&1) ans=ans*a%MOD;
			a=a*a%MOD; n>>=1;
		} return ans%MOD;
	}
public:
	explicit FastPow(ll a)
	{
		ll t1=a,t2=qpow(t1,65536); p1[0]=p2[0]=1;
		for (int i=1;i<65536;i++) p1[i]=p1[i-1]*t1%MOD;
		for (int i=1;i<65536;i++) p2[i]=p2[i-1]*t2%MOD;
	}
	ll operator()(unsigned n){return p2[n>>16]%MOD*p1[n&65535]%MOD;}
};

例题:块速递推

2. 不朴素

我们这个 r 也不一定取 p .

类似快速幂,我们拆

ax=axmodk(ak)x/k

左边预处理,右边递归做 .

这一般被叫做 k 进制倍增,当 k=2 时等价于快速幂 .

这个可以用来调节预处理复杂度和询问复杂度,例如 rp1/3 时 .

空间复杂度 O(klogkp) 时间复杂度 O(klogkp)O(logkp)(有错望指正).

例题:能量采集

2. 在线离散化

就是一个小工具 .

一个全自动 Hash 器,挺好用,可以让你避免离散化化化化化化

template<typename T>
struct pool
{
	unordered_map<T, unsigned> pol;
	unsigned cc = 0;
	unsigned get(T x)
	{
		auto ptr = pol.find(x);
		if (ptr == pol.end()){pol[x] = ++cc; return cc;}
		else return ptr -> second;
	}
};

例:程序设计分析 AC 代码(提交记录

using namespace std;
const int N = 1e6 + 500;
typedef long long ll;
int fa[N], n;
inline void init(int n){for (int i=0; i<=n; i++) fa[i] = i;}
int fnd(int x){return (fa[x] == x) ? x : fa[x] = fnd(fa[x]);}
void merge(int u, int v){fa[fnd(u)] = fnd(v);}
struct pool
{
	unordered_map<int, int> pol;
	int cc = 0;
	int get(int x)
	{
		auto ptr = pol.find(x);
		if (ptr == pol.end()){pol[x] = ++cc; return cc;}
		else return ptr -> second;
	}
}T;
void _()
{
	init(1e6);
	scanf("%d", &n);
	vector<pair<int, int> > query;
	for (int u, v, opt, i = 0; i<n; i++)
	{
		scanf("%d%d%d", &u, &v, &opt);
		if (opt == 1)
		{
			int U = T.get(u), V = T.get(v);
			merge(U, V);
		}
		else query.push_back(make_pair(u, v));
	}
	for (auto x : query)
	{
		int u = x.first, v = x.second, U = T.get(u), V = T.get(v);
		if (fnd(U) == fnd(V)){puts("NO"); return ;} 
	} puts("YES");
}
int main()
{
	int T; scanf("%d", &T);
	while (T--) _(); // solve
	return 0;
}

3. 邻接表

好像目前没啥应用

就是把邻接表链的链表改成别的数据结构,比如改成平衡树 / SkipList 就可以支持删边 .

4. C-Style 字符串小结

常见函数

  • strlen 长度
  • strcmp 比较(strcmpi 不区分大小写)
  • strcpy 复制
  • strcat 追加
  • strrev 字符串反转
  • strupr 转大写

全文读取:

void rdfile(const char* a)
{
	char* ptr=a;
	while ((*ptr=getchar()) && (*ptr!=EOF)) ++ptr;
}

5. 信息传递的一点研究

0. 一些小前置

D1 基环树是啥?link . 基环内向树是啥?所有边的方向都向着环的方向的基环树 .

D2 弱联通是啥?有向图去掉方向后的连通性


P

维护一个序列 a,支持

  1. 区间循环移 x
  2. 区间加
  3. 单点查

一次 1 操作拆成三次区间 reverse,用文艺平衡树即可 O(logn),于是 3 可以用 tag 做到 O(logn)2 可以递归 O(logn)

1. 朴素信息传递

题面大概是

给一个基环内向树森林求最小环

仨经典算法

  • 并查集
  • 拓扑排序
  • tarjan

一些别的算法

  • dfs,用并查集标记弱联通
  • Floyd 判圈法

2. 带修信息传递

题面大概是

给一个基环内向树森林求最小环

每次修改将 uv0 的边删掉,改成 uv1 .

现在除掉方向 .

从环上按顺序把每棵树的 DFS 序拼起来就当作整个森林的 DFS 序 .

维护 DFS 序的过程就是前置 P,区间加维护每个点到环的距离,就可以维护环长了 .

预处理 O(n),修改 O(logn),哈哈 .

或许可以 Euler Tour Tree??

假了请告诉我并爆 D 我的算法 qwq

upd: 这玩意其实叫 深度确定问题 .

upd:不是 depth determination,不能并查集,只能 log 平衡树 .

posted @   yspm  阅读(739)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示