• ACM课程设计课 Advance_Contest_1 解题报告 Apare_xzc


    ACM课程设计课Advance_Contest_1 解题报告

    xzc 2019/3/5 21:34


    这是赵尔敦老师ACM课程设计第一节课给ACM队员挂的题,不得不说难度还是有的,一共有四道题
    A. K-th Number(poj-2104) 查询区间第K大,主席树模板题
    B. Super Mario (HDU-4417) 线段树+离线处理(维护区间和,单点更新,区间查询)
    C. Bipartite Numbers (UVA-1051) 构造+打表+找规律+取模+素数(我认为)
    D. Bipartite Numbers(UVA-1052) dfs


    A. K-th Number

    题意:
    这道题poj 2104是主席树的入门题(模板题),求静态区间第K大,n个数,m个询问,每个询问查询数组a中区间[x,y]的第K小的数字是多少
    分析:
    我对主席树的理解:

    • 主席树是n棵线段树,第i棵线段树记录的是a[1]到a[i]的信息
    • 先把数组a[n]进行离散化处理,把a[i]替换为i在数组排序去重后的位置(是第几大)
    • 第x棵线段树记录的是a[1]到a[x]这个原数组的前缀的信息
    • 每一颗线段树有很多区间[L,R],第x课树的区间[L,R]记录的是从a[1]到a[x]这个范围内出现的数组的第L,第L+1…第R大的数的个数
    • 所以主席树就有了前缀和的性质
    • 由于相邻的两个前缀只有1个数不同,所以可以共用树的节点,相同的部分直接把左子树的指针指向原来的节点即可

    贴一个我的代码 (我把网上的板子用我喜欢的写法改了一下)
    今天上算法课又写了一遍
    其实区间的left和right不需要维护,只要查询的时候函数传参传入即可3月15号又写一遍
    附:前会长Y_Cl和卿爷的板子(指针写法,开了内存池)


    B. Super Mario
    没啥想说的,线段树+离线处理

    • 对查询按跳跃的高度h排序
    • 对所有点的高度排序
    • for(所有查询)把小于该查询的点都插入到线段树中,单点更新区间和
    • 查询区间和即可

    我的代码


    C. Bipartite Numbers

    题意:
    多组输入,每次输入一个正整数x,(x<=99999)
    要找一个x的倍数(大于x),满足这样的形式: 33333444
    前面有m个连续的s(s不为0),后面是n个连续的t,这个数要是x的倍数,求满足条件的最小的数 输入对应的m,s,n,t
    分析:
    这个题答案的数字可能会很大
    打表过后把1到99999所有的输入跑一遍要30分钟左右…
    我发现m最大可以为9966,n最大为156

    • 这道题我本来想的是把答案都处理出来,然后O(1)查询
    • 但是我发现900位的数都不行,1000(9976)位才行,没法打表
    • 我用python把1到1000个1这1000个大数分解质因数,打表跑了一晚上(只需要用99999以内的素数筛就可以了,大的素数没必要)
      python打表代码(分解大数的质因数)
    • 我的做法是暴力4个for:
    #伪代码:
    for x in range(1,10):
        for y in range(0,10):
            if x==y:
                continue
            for m in range(1,10000):
                for n in range(1,156): #打表打出来的
                if x*11111...11%k == y*11...1%k
                    ans = min(ans,...)
                    break .......
    

    我发现循环次数多的都是大质数*10看这个打的表, 那么能不能把这些特判掉呢?
    让我来给你分析分析:

    • 如果一个数是质数*10,那么它的倍数一定是以0结尾的,则t = 0
    • 那么这个质数一定是sssss…ss = s*11111…11的因数
    • 有因为他是个质数,那么s肯定和这个质数互质,那么必须满足:1111…1是这个质数的倍数
    • 那么问题转化为:最少几个连续的1是一个给定质数的倍数? 附一个9999以内质数表
    • 我们可以用秦九韶取模计算:
    int solve(int N)
    {
        int x = 1, cnt = 1;
        while(x)
        	++cnt, x = (x*10+1)%N;  
        return cnt;
    }
    

    我发现答案有的是N-2,有的是N-1,有的是N/2…一下子也没看出来什么统一的规律,没法O(1)得出结果(希望读者发现了规律的话和我交流一下),所以就跑一遍这个函数也挺快,总比4个for,N * 200 * 9 * 9快多了

    我的代码
    再附一个我自己写的 对拍程序 不用谢我


    D. Bit Compressor

    题意:
    压缩二进制信息,把n个连续的1替换成n的二进制形式,如果这样可以缩短二进制串的长度就替换(n>2)
    现在给一个压缩后的串,给出原串的长度和原串中1的个数,为是否能还原原串,结果是否唯一?
    思路:
    dfs,不想多说了,我好困,可能以后会补充吧
    具体见代码叭
    我代码的可读性还是很好的

    我的代码

    附: 福利哦
    我自己写的样例生成器
    把原始的01串正向压缩
    我又写了对拍程序


    附议:我们好强啊!

    ccnuacm17占领了vjuge Leaderboard的前排!

  • 相关阅读:
    Codeforces1335F Robots on a Grid
    BJOI2014 大融合
    洛谷 P1463 [SDOI2005]反素数ant && codevs2912反素数
    codeforce 570 problem E&& 51Nod-1503-猪和回文
    洛谷noip 模拟赛 day1 T1
    noip 2010 三国游戏
    noip 2013 华容道
    汕头市队赛 SRM 07 D 天才麻将少女kpm
    noip2012 普及组
    汕头市队赛 SRM 08 B
  • 原文地址:https://www.cnblogs.com/Apare-xzc/p/12243671.html
Copyright © 2020-2023  润新知