• 刷题记录(NC16692 [NOIP2001]求先序排列,NC204382 中序序列,NC23046 华华教月月做数学)


    NC16692 [NOIP2001]求先序排列

    题目链接

    关键点:

    1、已知中序和后序遍历,首先明确中序遍历是左根右,后序为左右根,先序为根左右,那么求根可以直接从后序的最后一位来找,然后在中序里找到该根(位置为pos),那么该pos的前面就为左子树,后面就为右子树,再以此类推

    2、设中序(pl,pr)后序(sl,sr)左子树为

    (pl,pos-1,sl,x)x-sl = pos-1-pl     ----------   x = pos-1-pl+sl;

    左子树为(pl, pos-1, sl, pos-1-pl+sl)

    同理右子树

    find(pos+1, pr, pos-pl+sl, sr-1);

    2、且无论是在左子树还是右子树,pl和pr的相差越来越近,因此有可能pl>pr,这是不存在的,因此在最开始要判断返回

    完整代码:

    1. # include
    2. # include
    3. using namespace std;
    4. string zhong, hou;
    5. void find(int lz, int rz, int lh, int zh)
    6. {
    7. if (lz>rz)
    8. return ;
    9. char root = hou[zh];
    10. cout<
    11. int i;
    12. for (i=lz; i<=rz; i++)
    13. {
    14. if (zhong[i] == root)
    15. break;
    16. }
    17. find(lz, i-1, lh, i-lz+lh-1);
    18. find(i+1, rz, i-lz+lh, zh-1);
    19. }
    20. int main()
    21. {
    22. cin>>zhong>>hou;
    23. int lz = 0, rz = zhong.size()-1, lh = 0, zh = hou.size()-1;
    24. find(lz, rz, lh, zh);
    25. return 0;
    26. }

    NC204382 中序序列

    题目链接

    关键点

    1、一样的思路,首先先序为根左右,后序为左右根,中序为左根右,且在先序中左里又可以分成根左右,然后再继续,直到只剩下一个结点,且该结点就为左节点,那么左子树的根为先序的第二个,然后再到后序里去找这个根(pos),后序里的左又可以分成左右根左右根,那么找到了左子树的根,即找到了后序里的左子树的最后

    2、先序(pl, pr), 后序(sl, sr),那么左子树 deal(pl+1, x, sl, pos) x-pl-1 = pos-sl

    x = pos-sl+pl+1;

    同理右子树deal (x+1, pr,  pos+1, sr-1)

    同样的,还是得判断区间是否存在

    完整代码

    1. vector<int>v;
    2. class Solution {
    3. public:
    4. void deal(int pr, int pl, int sr, int sl, vector<int> &pre, vector<int> &suf)
    5. {
    6. if (pr==pl)
    7. {
    8. v.push_back(pre[pr]);
    9. return ;
    10. }
    11. int x = pre[pr+1];
    12. int pos = -1;
    13. for (int i=sr; i<=sl; i++)
    14. {
    15. if (suf[i]==x)
    16. {
    17. pos = i;
    18. break;
    19. }
    20. }
    21. deal(pr+1, pr+1+pos-sr, sr, pos, pre, suf);
    22. v.push_back(pre[pr]);
    23. if (sl-1>=pos+1)deal(pr+1+pos-sr+1, pl, pos+1, sl-1, pre, suf);
    24. }
    25. vector<int> solve(int n, vector<int>& pre, vector<int>& suf) {
    26. deal(0, pre.size()-1, 0, suf.size()-1, pre, suf);
    27. return v;
    28. }
    29. };

    NC23046 华华教月月做数学

    题目链接

    关键点

    1、快速幂和快速乘,快速幂是将次方分成二进制数,而快速乘将一个乘数分成二进制数(看成n个m相加)

    完整代码:

    1. # include
    2. # include
    3. using namespace std;
    4. typedef long long ll;
    5. int t;
    6. ll a, b, p;
    7. ll cheng(ll x, ll y)
    8. {
    9. ll base = x%p;
    10. ll ans = 0;
    11. while (y)
    12. {
    13. if (y&1)
    14. ans = (ans+base)%p;
    15. base = (base+base)%p;
    16. y>>=1;
    17. }
    18. return ans;
    19. }
    20. ll mi()
    21. {
    22. ll ans = 1;
    23. ll base = a%p;
    24. while (b)
    25. {
    26. if (b&1)
    27. ans = cheng(ans, base)%p;
    28. base = cheng(base, base)%p;
    29. b>>=1;
    30. }
    31. return ans;
    32. }
    33. int main()
    34. {
    35. scanf("%d", &t);
    36. while (t--)
    37. {
    38. scanf("%lld%lld%lld", &a, &b, &p);
    39. cout<<mi()<
    40. }
    41. return 0;
    42. }

  • 相关阅读:
    系统架构知识点总结-DX的笔记
    javaweb高校实验室管理系统ssm
    [学习笔记] 概率与期望及其应用
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    代理IP与Socks5代理:跨界电商智能爬虫的引擎与安全壁垒
    Spring依赖注入
    go 学习01
    第五篇 基于JSP 技术的网上购书系统——主页面和登录页面实现(网上商城、仿淘宝、当当、亚马逊)
    强化学习总结1 马尔科夫过程
    java精准扶贫项目管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
  • 原文地址:https://blog.csdn.net/m0_60531106/article/details/125882611