码迷,mamicode.com
首页 > 其他好文 > 详细

被虐的两道数论题

时间:2015-11-19 22:16:12      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

         我说……我这么闲,那么……写篇日志吧,谨以此纪念我无限趋向于0的智商,那天……犯了个傻的两道题……顺便orz一下HGR以及HYY神犇……
        Problem A:
        给定n,k,求任意一个序列a,使得∏(1≤i≤k)(1+1/ai)=1+(2^k-1)/n。(1≤n≤2^31,1≤k≤31)
        本来这题目是很水的……但是……我当即立断,机智地化了简:(Σ(b∈[1,k])ab1ab2ab3…abp)/∏(1≤i≤k)ai=(2^k+n-1)/n。随后我发现,ai与ai+1约分后必须取遍n的质因数(好吧,预处理先把右边约分),然后我开始对n进行分解,然后各种枚举……由于我的程序比较挫,它一度陷入死循环……努力了一个多小时后……我发现它……比暴力还慢,于是我有改呀改,改到没时间写第三题水水的trie。我暴搜出所有情况,然后各种剪枝……搞到最后只拿到30分的暴力分,深深的维和感。
        后来看到了题解,发现我傻了,题解把(2^k+n-1)/n进行了简单的分解:当2丨n时,(2^k+n-1)/n=((2^(k-1)+n/2-1)/(n/2))*(1+1/(2^k+n-2)),否则(2^k+n-1)/n=((2^(k-1)+(n+1)/2-1)/((n+1)/2))*(1+1/n),然后一阵递归,边界嘛,显然k=1时,a={n}看到题解后不到5分钟就A了这题目T_T。
        如此水的代码,我就不发了……
        Problem B:
        给定n,m(1≤n,m≤10^16),问长度为m的只由1~n间数字构成的圆周序列的个数。
        一开始看,嗯,圆排列,就这么简单?然后发现我跪了,根本不一样嘛,于是我使劲想,却也只弄出来60分做法(必须承认,这是暴力分),然后,HGR大神给了一番讲解,但是整个教室似乎没人听懂(HYY大神大概是懂了……)。HGR大神大概是算计好的,在恰当的时刻来巡视我们,然后机智接受了全教室唯一一个妹纸的再讲解邀请,然后给了她各种福利(就是厚厚的一本书,看内容大概是排列组合一类的,哼,我有人品神器《初等数论》),但是似乎还是没人懂(他们都不知道欧拉函数,当然听不懂)。当晚,我把《初等数论》放在床头,于是我失眠了,然后想出了这题目自己的证明,比HGR的好懂多了(那是因为我只是个苣蒻),原来的定理是这样的:记序列个数为f(n,m),那么我们有f(n,m)=(1/m)*(Σ(1≤l≤m)n^(gcd(l,m)))=(1/m)*(Σ(d丨m)(n^d)*φ(m/d))。然后我给出一个“生动形象”的证明:
        首先,我们有m*f(n,m)=Σ(a0a1a2...am-1∈[1,n])Σ(0≤l<m)[a0a1a2...am-1=alal+1...am-1a0...al-1],这里的中括号表示当括号内表达式为true时取1,否则取0。传说中HGR大神就是这个东西一直给妹纸讲不清,我也不知道我能不能说清。我们可以想象一下a0a1a2...am-1∈[1,n]作为全集的一个集合,显然f(n,m)取了集合中的一部分,而假如我们对f(n,m)中每个圆周序列进行旋转,就会产生m*f(n,m)个序列。比如序列AB可以扩展成AB和BA,但是BA是不存在于f(n,m)中的(在已有AB的情况下),那么全部旋转后就能取遍f(n,m)的补集。然而对于序列AA,旋转后产生两个AA,此时出现重复,即在取遍全集的基础上部分元素被多次取到。很容易发现当l=0时,a0a1a2...am-1=alal+1...am-1a0...al-1显然成立,此时就取遍了全集,而当l≠0时,等式一旦成立,取到的点一定是已经被重复覆盖(比如序列AA),然后……式子就证明完了,真是“生动形象”的证明。
        接下来我们考虑将式子化简,首先,交换两个Σ是不会破坏结果的,那么式子变成Σ(0≤l<m)Σ(a0a1a2...am-1∈[1,n])[a0a1a2...am-1=alal+1...am-1a0...al-1],于是乎,我们可以对单个点进行讨论啦。接下来的证明,HGR大神用了各种同余,以及拓展欧几里得定理(所以大家都听不懂),作为一个苣蒻,我就不写了,我同样有“生动形象”的证明:
        为了帮助大家理解,我们可以先考虑 l丨m的情况,此时,我们可以把长度为m的序列分块,每块长度为l,由a0a1a2...am-1=alal+1...am-1a0...al-1显然可以分解成当i≡j(mod l)时,ai=aj,那假如我们确定了ai(0≤i<l),我们就能确定ai+kl(1≤k<m/l),于是乎,只要我们确定了a0...al-1,我们就能确定整个序列,所以序列的可能性,只有n^l 种,于是m*f(n,m)=Σ(1≤l≤m)n^(gcd(l,m)),就成立了。但是如果l不整除m,我们记d=gcd(l,m),此时同样可以对序列进行分块,每块长度为d,由于当i≡j(mod l)时,ai=aj,只要确定了ai(0≤i<l),我们就能确定a(i+kl)mod m(1≤k<m/d),显然,i+kd有可能超出m的边界(所以我写了mod m),此时由于一共有m/d个块,而m/d又与l互质,我们可以对原图进行压缩,看成m/d的d个剩余系,因为(l,m/d)=1,由于什么剩余系定理(不知道应该叫什么),i+kd是可以取遍整个剩余系的,于是,只要确定了ai(0≤i<d),i在其他块的映射位置也都能确定,所以合法的序列只有n^d种。该做法能拿90分。
         继续化简,很容易可以得到m*f(n,m)=Σ(d丨m)(n^d)*φ(m/d),证明的话我就不废话了(显然……)。再显然,我们可以用神奇的Pollard-rho算法,在四次根号m的复杂度下对m进行质因数分解,利用φ(n)的积性,在计算所有d的同时顺手把φ(m/d)给算出来,然后……就可以A啦……
        代码……?你想多了……
        停电导致本文进度一度停滞(渣手机写不了日志),谨以此纪念我完跪的二中培训……

被虐的两道数论题

标签:

原文地址:http://www.cnblogs.com/Enceladus/p/4979056.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!