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的前排!

你可能感兴趣的:(解题报告)