新生赛以后就正式成为一名acmer啦 ~虽然没有打过比赛呜呜呜

要好好学算法,拿一个牌牌嘛~

这里就记录算法学习情况,也怕自己偷懒,学一个就记录,看看长时间拖更就是在摸鱼,摸鱼和鸽子都是本质 ,加油!

开坑时间 2020.12.9

2020.12.9 今日快排走起(加模板)

quicksort!

  1. void quicksort(ll a[],ll l,ll r)
  2. {
  3. if(l>r) return ; //递归跳出条件
  4. ll temp=a[l]; ll i=l; ll j=r; //基准态定义和l,r定义
  5. while(i!=j) //i,j不碰头
  6. {
  7. while(a[j]>=temp&&i<j) j--; //注意i<j条件,不然存在相等的数就无法跳出循环
  8. while(a[i]<=temp&&i<j) i++; //同上
  9. if(i<j) swap(a[i],a[j]);
  10. }
  11. a[l]=a[i]; //基准态交换
  12. a[i]=temp;
  13. quicksort(a,l,i-1); //递归
  14. quicksort(a,i+1,r);
  15. }

快排是分治的思想,设定一个基准态,将比基准态小的数放在左边,将比基准态大的数放在后边,然后将基准态归位,完成一个调整,这样一来部分数顺序已经调整,在分成左右区间进去递归,重复上述过程,已经归位的基准态不用管,(l,i-1)和(i+1,r)进行下一步递归,此时i为已经归位的数不需要再次递归。

个人理解: 快排原理是根据已经排好的数有一个规律:比n小的在n左边,比n大的在n的右边,所以左右遍历调整错误顺序数的位置,最后遍历完后(i==j)时,左右均已经遍历完,此时基准态归位完成一个循环,再进行区间二分,进行递归。

时间复杂度: 平均O(n)=nlogn,最坏的情况会退化到O(n)=n^2,最好情况也是O(n)=nlogn.

sort大法好


2020.12.10 分治里面归并少不了

mergesort!

  1. int temp[200000]; //归并需要额外的空间存放调整完后的数据
  2. void merge_sort(int q[], int l, int r)
  3. {
  4. if(l>=r) return;
  5. int mid=l+r >> 1;
  6. merge_sort(q,l,mid) , merge_sort(q,mid+1,r); //分解
  7. // 调整顺序
  8. int k=0, i=l, j=mid+1;
  9. while(i<=mid&&j<=r)
  10. if(q[i]<=q[j]) temp[k++]=q[i++];
  11. else temp[k++]=q[j++];
  12. while(i<=mid) temp[k++]=q[i++];
  13. while(j<=r) temp[k++]=q[j++];
  14. for(i=l,j=0;i<=r;i++,j++) q[i]=temp[j];
  15. }

y总的一个函数完成归并模板orz 记录一下

归并排序:思路也是分治思想,先分成若干小部分,在单独递归处理后,合并在一起。为了满足数组有序,我们可以一直二分到子数组只有两个数,在一个个调整顺序,最后左右两边实行最后一次合并到另外一个数组中,完成所有排序。如下图:



调整顺序中: 用两个指针指向两个子数组的头,相互比较,把较小的数存在temp数组中,然后把指向原数的指针向后移动一位,继续比较重复上述过程,如果某个指针到头了,就把另外剩下的数全部补在temp数组中完成一次调整顺序,最后把temp数组中的数据移动在需要排序的数组中即可。

确实很强呐呜呜呜


2020.12.12 二分查找板子来一个~

half_find!

自己的中式英语

binary_find

别问11号干嘛去了,问就是摸鱼去了 (比赛加摸鱼)

  1. int half_find(int a[],int l,int r,int b)
  2. {
  3. while(l<r)
  4. {
  5. int mid=l+r >>1;
  6. if(a[mid]>b) r=mid; //这里判断条件改动与lower_bound和upper_bound用法一致
  7. else l=mid+1;
  8. }
  9. return l;
  10. }

二分的板子边界一堆,直接记忆这个 实在不行stl大法好嘛 ,尽量自己写呐,简单的板子好记,原理也简单,记住if后不加,else后加1就行~,主要是边界问题难受最后return l和r一样的,因为此时l==r。

y总yyds


2020.12.14 静态链表(单链表)(数据结构冲冲冲)

Linked_list(Static)!

别问...13号干嘛去 gugugu 湖南停电停水大学实锤

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<vector>
  5. #include<cstdio>
  6. #include<cmath>
  7. #define int ll
  8. #define ll long long
  9. using namespace std;
  10. ll val[200000];
  11. ll p[200000];
  12. ll idx;
  13. ll head;
  14. void init() //创建静态单链表
  15. {
  16. head=-1;
  17. idx=0;
  18. }
  19. void head_add(ll x) //在head处插入结点
  20. {
  21. val[idx]=x,p[idx]=head;
  22. head=idx++;
  23. }
  24. void nor_add(ll k,ll x) //在k处插入一个结点
  25. {
  26. val[idx]=x,p[idx]=p[k];
  27. p[k]=idx++;
  28. }
  29. void nor_remove(ll k) //把k后的一个结点删除
  30. {
  31. p[k]=p[p[k]]; //p[k++]不对注意!
  32. }
  33. void head_remove()
  34. {
  35. head=p[head];
  36. }
  37. ll n;
  38. ll x,y;
  39. char a;
  40. signed main()
  41. {
  42. cin>>n;
  43. init();
  44. while(n--)
  45. {
  46. cin>>a;
  47. if(a=='H')
  48. {
  49. cin>>x;
  50. head_add(x);
  51. }
  52. else if(a=='D')
  53. {
  54. cin>>x;
  55. if(x) nor_remove(x-1);
  56. else head_remove();
  57. }
  58. else if(a=='I')
  59. {
  60. cin>>x>>y;
  61. nor_add(x-1,y);
  62. }
  63. }
  64. for(int i=head;i!=-1;i=p[i])
  65. {
  66. cout<<val[i]<<" ";
  67. }
  68. cout<<endl;
  69. return 0;
  70. }

原题链接acwing的~

总结一下所谓静态链表:用数组模拟链表(原因: 动态链表非常非常耗时间,malloc和new速度很慢,对acmer很不友好),用双数组模拟链表,实现某些功能(树图警告),val表示实际存入的值,p表示下一个数的下标(等价于链表),再加上一个head表示头指针,idx表示剩余空间的第一位下标,可调用,创建新结点)(又是一个用空间换时间的呜呜呜)

几种基本操作:

1.创建新链表

  1. void init() //创建静态单链表
  2. {
  3. head=-1;
  4. idx=0;
  5. }

将head指向-1(表示null),idx=0表示数组均可用。

2.添加结点

  1. void head_add(ll x) //在head处插入结点
  2. {
  3. val[idx]=x,p[idx]=head;
  4. head=idx++;
  5. }
  6. void nor_add(ll k,ll x) //在k处插入一个结点
  7. {
  8. val[idx]=x,p[idx]=p[k];
  9. p[k]=idx++;
  10. }

插入要分头插其他结点插

头插需要修改head,其他就不要需分开

先创建一个结点,再将创建的结点指向k或者头指向的那一位,最后将头或者k指向创建的数组, 记住idx要++ 这一步与上一步可以合并(因为可用的已经用了一位idx要往后移一位)

3.删除结点

  1. void nor_remove(ll k) //把k后的一个结点删除
  2. {
  3. p[k]=p[p[k]]; //p[k++]不对注意!
  4. }
  5. void head_remove()
  6. {
  7. head=p[head];
  8. }

同理删除也要分头和其他y总翻车现场 还是head的问题,这里注意,代码里面有注意的,不能写成p[k++]因为有时候k++不一定是k后面那一位,要用p[p[k]]表示k后面那一位,与指针类似。

4.链表遍历

  1. for(int i=head;i!=-1;i=p[i]) cout<<val[i]<<" ";

从head开始顺着p开始遍历,如果i==-1(即此时遇到尾结点,跳出循环),同样注意,后面不是i++,而是把p[k]给i,表示指针后移一位。

就这样自己晚个安 绝对不熬夜


2020.12.15 双链表!

  1. #include<bits/stdc++.h>
  2. #define int ll
  3. #define ll long long
  4. using namespace std;
  5. const int N = 2e6;
  6. ll val[N], l[N], r[N],idx;
  7. ll m;
  8. void init()
  9. {
  10. r[0]=1,l[1]=0;
  11. idx=2;
  12. }
  13. void add(int k,int x) //k后
  14. {
  15. val[idx]=x,r[idx]=r[k],l[idx]=k;
  16. l[r[k]]=idx,r[k]=idx++;
  17. }
  18. void remove(int k) //删除第k个点
  19. {
  20. r[l[k]]=r[k];
  21. l[r[k]]=l[k];
  22. }
  23. signed main() {
  24. ios::sync_with_stdio(0);
  25. cin.tie(0);
  26. init();
  27. cin>>m;
  28. while(m--)
  29. {
  30. string a;
  31. int k,x;
  32. cin>>a;
  33. if(a=="L")
  34. {
  35. cin>>x;
  36. add(0,x);
  37. }
  38. else if(a=="R")
  39. {
  40. cin>>x;
  41. add(l[1],x);
  42. }
  43. else if(a=="D")
  44. {
  45. cin>>k;
  46. remove(k+1);
  47. }
  48. else if(a=="IL")
  49. {
  50. cin>>k>>x;
  51. add(l[k+1],x);
  52. }
  53. else if(a=="IR")
  54. {
  55. cin>>k>>x;
  56. add(k+1,x);
  57. }
  58. }
  59. for(int i=r[0];i!=1;i=r[i]) cout<<val[i]<<" ";
  60. cout<<endl;
  61. return 0;
  62. }

双链表: 一个结点同时有指向左右两边的指针,L[]和R[],没有头指针,将0,1分别做为链表的头尾。不含其他实际数值,在0,1之间插入删除,其他与单链表类似。注意双向都要考虑.

最后注意: 链表中不要出现++操作。要用指针,也就是数组对下一位进行操作,用R[]表示下一位,L[]表示上一位。

over~


2021.1.3新年快乐...~ gugugu

我,大鸽子,来更新了~ (逃

来一个快速幂板子和费马小定理

快速幂板子

  1. ll qpow(ll a, ll x)
  2. {
  3. ll re = 1;
  4. while(x)
  5. {
  6. if(x&1) re = re * a % M;
  7. a = a * a % M;
  8. x = x >> 1;
  9. }
  10. return re;
  11. }

M为防止数太大除的余数,a为底数,x为指数,思想跟二分差不多,将质数一次循环就除二,底数自己乘一次减少计算机次数。

费马小定理

原公式: a ^ (p-1) = 1 (mod)

费马小定理主要是防止指数太大时,如果是求同余的数,可以大大减少指数的大小

升级公式 : ( a ^ n ) % p = ( a ^ ( n % (p -1) ) % p )

也就是当n很大的时候,若p是质数, a 与p互质 , n可以先与(p-1)取模以后再进行整体%P,因为两数同余,结果一样。


2021.1.10别问,问就是期末考试 咕咕咕

高精度板子整理

高精度加法

  1. #include<bits/stdc++.h>
  2. #define fp for(int i=1;i<=n;i++)
  3. #define ll long long
  4. using namespace std;
  5. vector<ll> add(vector<ll> &A , vector<ll> &B)
  6. {
  7. ll lena=A.size();
  8. ll lenb=B.size();
  9. vector<ll> C;
  10. ll t=0;
  11. for(int i=0;i<lena||i<lenb;i++)
  12. {
  13. if(i<lena) t+=A[i];
  14. if(i<lenb) t+=B[i];
  15. C.push_back(t%10);
  16. t/=10;
  17. }
  18. if(t) C.push_back(1);
  19. return C;
  20. }
  21. int main()
  22. {
  23. string a,b;
  24. vector<ll> A,B,C;
  25. cin>>a>>b;
  26. ll lena=a.size();
  27. ll lenb=b.size();
  28. for(int i=lena-1;i>=0;i--) A.push_back(a[i]-'0');
  29. for(int i=lenb-1;i>=0;i--) B.push_back(b[i]-'0');
  30. C=add(A,B);
  31. ll lenc=C.size();
  32. for(int i=lenc-1;i>=0;i--) cout<<C[i];
  33. cout<<endl;
  34. return 0;
  35. }

用vector代替数组,因为有个size函数,方便操作,函数里面t有多重身份注意。

高精度减法

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define s size()
  4. #define pb push_back
  5. #define vl vector<ll>
  6. using namespace std;
  7. bool cmp(vl &a,vl &b)
  8. {
  9. if(a.s!=b.s) return a.s>b.s;
  10. for(int i=a.s-1;i>=0;i--)
  11. if(a[i]!=b[i]) return a[i]>b[i];
  12. return true;
  13. }
  14. vl sub(vl &a,vl &b)
  15. {
  16. ll lena=a.s;
  17. vl c;
  18. for(int i=0,t=0;i<lena;i++)
  19. {
  20. t=a[i]-t;
  21. if(i<b.s) t-=b[i];
  22. c.pb((t+10)%10);
  23. if(t<0) t=1;
  24. else t=0;
  25. }
  26. while(c.s>1&&c.back()==0) c.pop_back();
  27. return c;
  28. }
  29. int main()
  30. {
  31. string A,B;
  32. vl a,b,c;
  33. cin>>A>>B;
  34. ll lena=A.s;
  35. ll lenb=B.s;
  36. for(int i=lena-1;i>=0;i--) a.pb(A[i]-'0');
  37. for(int i=lenb-1;i>=0;i--) b.pb(B[i]-'0');
  38. if(cmp(a,b))
  39. {
  40. c=sub(a,b);
  41. ll lenc=c.s;
  42. for(int i=lenc-1;i>=0;i--) cout<<c[i];
  43. cout<<endl;
  44. }
  45. else
  46. {
  47. c=sub(b,a);
  48. ll lenc=c.s;
  49. cout<<"-";
  50. for(int i=lenc-1;i>=0;i--) cout<<c[i];
  51. cout<<endl;
  52. }
  53. return 0;
  54. }

减法的话要先判断减数和被减数的大小,先决定输出+,-号,(该代码未考虑负数的相减),然后通过cmp控制大的为被减数,再最后注意借位问题就好啦。

还要注意去掉前导0.

高精度乘法

先是高精度×小数

  1. #include<bits/stdc++.h>
  2. #define s size()
  3. #define pb push_back
  4. #define vl vector<long long>
  5. typedef long long ll;
  6. using namespace std;
  7. vl mul(vl &a,ll b)
  8. {
  9. vl c;
  10. ll lena=a.s;
  11. for(int i=0,t=0;i<lena||t;i++)
  12. {
  13. if(i<lena) t+=a[i]*b;
  14. c.pb(t%10);
  15. t/=10;
  16. }
  17. while(c.s>1&&c.back()==0) c.pop_back();
  18. return c;
  19. }
  20. int main()
  21. {
  22. string A;
  23. ll b;
  24. vl a,c;
  25. cin>>A>>b;
  26. ll lena=A.s;
  27. for(int i=lena-1;i>=0;i--) a.pb(A[i]-'0');
  28. c=mul(a,b);
  29. ll lenc=c.s;
  30. for(int i=lenc-1;i>=0;i--) cout<<c[i];
  31. cout<<endl;
  32. return 0;
  33. }

把小数看成整体进行计算,同样注意要去掉前导0.

高精度*高精度

  1. #include<bits/stdc++.h>
  2. #define s size()
  3. #define pb push_back
  4. #define vl vector<long long>
  5. typedef long long ll;
  6. using namespace std;
  7. vl mul(vl &a,vl &b)
  8. {
  9. ll lena=a.s;
  10. ll lenb=b.s;
  11. vl c(lena+lenb,0);
  12. for(int i=0;i<lena;i++)
  13. for(int j=0;j<lenb;j++) c[i+j]+=a[i]*b[j];
  14. ll lenc=c.s;
  15. for(int i=0,t=0;i<lenc;i++)
  16. {
  17. t+=c[i];
  18. c[i]=t%10;
  19. t/=10;
  20. }
  21. while(c.s>1&&c.back()==0) c.pop_back();
  22. return c;
  23. }
  24. int main()
  25. {
  26. string A,B;
  27. vl a,b,c;
  28. cin>>A>>B;
  29. ll lena=A.s;
  30. ll lenb=B.s;
  31. for(int i=lena-1;i>=0;i--) a.pb(A[i]-'0');
  32. for(int i=lenb-1;i>=0;i--) b.pb(B[i]-'0');
  33. c=mul(a,b);
  34. ll lenc=c.s;
  35. for(int i=lenc-1;i>=0;i--) cout<<c[i];
  36. cout<<endl;
  37. return 0;
  38. }

也是实现手算乘法,用法比较巧妙,建议全文背诵/doge

高精度除法

只贴高精度除低精度,高精度除高精度很麻烦,而且比赛都是会取模的

  1. #include<bits/stdc++.h>
  2. #define s size()
  3. #define pb push_back
  4. #define vl vector<long long>
  5. typedef long long ll;
  6. using namespace std;
  7. vl div(vl &a,ll b,ll &r)
  8. {
  9. vl c;
  10. ll lena=a.s;
  11. r=0;
  12. for(int i=lena-1;i>=0;i--)
  13. {
  14. r=r*10+a[i];
  15. c.pb(r/b);
  16. r=r%b;
  17. }
  18. reverse(c.begin(),c.end());
  19. while(c.s>1&&c.back()==0) c.pop_back();
  20. return c;
  21. }
  22. int main()
  23. {
  24. string A;
  25. ll b;
  26. vl a,c;
  27. ll r;
  28. cin>>A>>b;
  29. ll lena=A.s;
  30. for(int i=lena-1;i>=0;i--) a.pb(A[i]-'0');
  31. c=div(a,b,r);
  32. ll lenc=c.s;
  33. for(int i=lenc-1;i>=0;i--) cout<<c[i];
  34. cout<<endl<<r<<endl;
  35. return 0;
  36. }

其中由于除法是从最高位运算的,要使与其他三个互通,函数里面用了reverse函数调换了位置,时间复杂度有点大,但是方便融合

四个高精度完毕


ACM基础板子的更多相关文章

  1. JAVA ACM 基础

    java ACM Java做ACM-ICPC的特点: (1) 在一般比赛中,Java程序会有额外的时间和空间,而实际上经过实验,在执行计算密集任务的时候Java并不比C/C++慢多少,只是IO操作较慢 ...

  2. ACM基础算法入门及题目列表

    对于刚进入大学的计算机类同学来说,算法与程序设计竞赛算是不错的选择,因为我们每天都在解决问题,锻炼着解决问题的能力. 这里以TZOJ题目为例,如果为其他平台题目我会标注出来,同时我的主页也欢迎大家去访 ...

  3. java编程acm基础

    java还是不错的昂! import java.util.*; import java.io.*; public class text{ static int a=100; public static ...

  4. ACM基础(一)

    比较大的数组应尽量声明在main函数外,否则程序可能无法运行. C语言的数组并不是“一等公民”,而是“受歧视”的.例如,数组不能够进行赋值操作: 在程序3-1中,如果声明的是“int a[maxn], ...

  5. C++ ACM基础

    一.C++结构体 #include <iostream> using namespace std; struct Point{ int x; int y; Point(int x=0,in ...

  6. Python3 acm基础输入输出

    案例一:输入字符串分割并转化成多个int数值 a, b= map(int, input().split()) try: while True: a, b= map(int, input().split ...

  7. 【基础数位DP-模板】HDU-2089-不要62

    不要62 Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepted Su ...

  8. 【题解】【排列组合】【素数】【Leetcode】Unique Paths

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  9. JSU 2013 Summer Individual Ranking Contest - 5

    JSU 2013 Summer Individual Ranking Contest - 5 密码:本套题选题权归JSU所有,需要密码请联系(http://blog.csdn.net/yew1eb). ...

随机推荐

  1. 【新阁教育】台达DVP-ES3 ModbusTCP通信案例

    本文主要针对台达DVP-ES3系列PLC,实现上位机与PLC之间的ModbusTCP通信. 一.硬件说明 DVP-ES3 系列为高阶应用可编程控制器, CPU 内置4 组高速计数器输入.4组轴输出(脉 ...

  2. java例题_28 冒泡排序

    1 /*28 [程序 28 排序算法] 2 题目:对 10 个数进行排序 3 程序分析:可以利用选择法,即从后 9 个比较过程中,选择一个最小的与第一个元素交换, 下次类推, 4 即用第二个元素与后 ...

  3. odoo 安装配置

    Linux ubuntu 环境 1.建个python虚环境 也可用其他替代 virtualenv env 2.找个稳定版本下载 wget https://nightly.odoo.com/8.0/ni ...

  4. 有了CMDB,为什么还需要应用配置管理?

    有了CMDB,为什么还需要应用配置管理? 你不妨先停下来,思考一下这个问题. 我抛出的观点是: CMDB是面向资源的管理,应用配置是面向应用的管理. 请注意,这里是面向"资源",不 ...

  5. js 一数组分割成若干个数组,并装换成字符串赋个li标签

    success: function (datas) { //请求成功后处理函数. var htmltext = ''; var data = datas.result; console.log(dat ...

  6. ISP算法:深入聊聊lens shading

    一.简介 关于什么是成像中的lens shading这里直接引用一句英文的definition:"The term shading describes the light fall-off ...

  7. OO_Unit4暨学期总结

    OO_Unit4暨学期总结 一.本单元架构设计 1.1 第13次作业架构设计 就我个人而言,这次作业应该是本单元难度最大的一次作业,原因在于陡然转向UML后,对UML各个元素的关系理解需要先下一番功夫 ...

  8. RocketMq(一)初识

    消息中间件基本上是互联网公司必用的一个中间件,为什么要使用MQ,当然是因为能给我们的系统带来很多好处. 消息队列简单来说是一种先进先出的数据结构,先简单认识下. 一.应用场景 消息中间件主要应用场景主 ...

  9. 指方画圆之Java设计模式:适配器模式

    目录 应用场景 适配器模式 定义 意图 主要解决问题 何时使用 优缺点 指鹿为马VS指方为圆 指鹿为马 指方为圆 应用场景 使用者依赖的接口与提供者的接口不匹配时,就加一层适配,而不修改两端的代码 生 ...

  10. Day13_68_中止线程

    中止线程方法一 * 在线程类中定义一个bollean类型的变量,默认值设置为ture,如果想要中断线程,只需要将该boolean类型的变量设置为false就可以了 * 代码 package com.s ...