1.7-1.14周报,关于一周的学习总结

本周学习知识点:并查集,最短路,最小生成树,线段树,基础博弈论(巴什游戏,尼姆游戏,威佐夫,斐波那契),同余定理,扩展欧几里得,乘法逆元,线性筛,stl,欧拉定理,唯一分解定理,组合数学。

已掌握知识点:并查集,最小生成树,线段树,基础博弈论,同余定理,扩展欧几里得,乘法逆元,线性筛,组合数学(懂了个大概)。

并查集(disjoint set):合并+查找。查找就是找这个元素的根。合并就是在根与根之间建立关系,让他们拥有同一个根。三个函数:初始化+查找+合并

并查集的例题加题解。

算法打卡第一天——公司竞争(并查集)_ly14158的博客-CSDN博客

算法打卡第一天之——并查集(他自称是一道板子题,至于他是啥,咱也不知道)_ly14158的博客-CSDN博客

并查集+查找可以用来进行线段树的求解。

并查集+Kruskal:算法打卡第二天之——修复公路(并查集+Kruskal算法)_ly14158的博客-CSDN博客

线段树的算法:Kruskal +Prim算法。克鲁斯卡尔算法稍微掌握,但是Prim算法并未完全掌握。克鲁斯卡尔算法大致可以按照并查集+结构体排序。而线段树内部可以跟二分算法联系在一起。主要分为三个函数:build+query+modify。线段树可以用来解决单点修改和区间修改。在解决这类问题用到线段树的时候,一定要记得更新(pushup),而在区间修改的时候要记得修改值下放的函数(pushdown)。找最值的时候是直接更换值,而找区间和最大的则是叠加。

最后附上线段树的板子题。

#include<bits/stdc++.h>
#define N 900000
using namespace std;

int n;
int a[N];

struct tree{
	int l,r;
	int sum;
	int mid(){
		return (l+r)/2;
	}
}tre[N];

void pushup(int rt)
{
	tre[rt].sum=tre[rt*2].sum+tre[rt*2+1].sum;
}

void bulid(int rt,int l,int r)
{
	if(l==r){
		tre[rt]={l,r,a[l]};
	}else {
		tre[rt]={l,r};
		int mid=tre[rt].mid();
		bulid(rt*2,l,mid);
		bulid(rt*2+1,mid+1,r);
		pushup(rt);
	}
}

int query(int rt,int l,int r)
{
	if(tre[rt].l>=l&&tre[rt].r<=r)
	{
		return tre[rt].sum;
	}else {
		int mid=tre[rt].mid();
		int ans=0;
		if(l<=mid)
		{
			ans+=query(rt*2,l,r);
		}if(r>mid)
		{
			ans+=query(rt*2+1,l,r);
		}return ans;
	}
}

void modify(int rt,int x,int y)
{
	if(tre[rt].l==x&&tre[rt].r==x)
	{
		tre[rt].sum+=y;
	}else {
		int mid=tre[rt].mid();
		if(x<=mid)
		{
			modify(rt*2,x,y);
		}else {
			modify(rt*2+1,x,y);
		}pushup(rt);
	}
}
int main()
{
	int T,k=1;
	scanf("%d",&T);
	while(T--){
		printf("Case %d:\n",k++);
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}bulid(1,1,n);
		while(1){
			char op[2];
			int c,d;
			scanf("%s",op);
			if(op[0]=='E'){
				break;
			}scanf("%d %d",&c,&d);
			if(op[0]=='Q'){
				printf("%d\n",query(1,c,d));
			}else if(op[0]=='A'){
				modify(1,c,d);
			}else if(op[0]=='S'){
				modify(1,c,-d);
			}
		}
	}return 0;
}

基础博弈论:直接放笔记吧。(字丑别骂)

 

 接下来就是数学的世界

 同余定理:如果a除以m得余数r,则a与r对m取模同余。每个整数必与0~(m-1)中的一个数字模m同余。

扩展欧几里得:是欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式子ax+by=gcd(a,b);如果a是负数,可以把问题转化成|a|(-x)+by=gcd(|a|,b).,然后令x'=(-x)。

乘法逆元:是指数学领域群G中任意一个元素a,都在G中有唯一的逆元a‘,具有性质a×a'=a'×a=e,其中e为该群的单位元。

这就是这三个概念的定义,但是说归说,写出来倒没有那么复杂;使用了递归思想,代码就变简洁起来了。

线性筛:一个比埃式筛还要快的筛法。他的时间复杂度是O(n)。

isprime(int n){
    for(itn i=2;i<=N;i++){
        if(!num[i]){
            prime[cnt++]=i;
            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                num[i*prime[j]]=1;
                if(i%prime[j]==0){
                    break;
                   }
                }
            }
        }
    }
}

 组合数学:主要是排列组合,其中还有卢卡斯定理。

剩下的还没有太理解,容我消化消化吧wwww

 

Guess you like

Origin blog.csdn.net/ly14158/article/details/122501495