Codility上的练习 (10)

(1)ChocolatesByNumbers
N块巧克力,从0到N - 1编号,排成一个圈。从0号开始吃,如果上一次吃了x号,这一次吃(x + M) % N号,如果该号码已经存在,则停止。问结束前,吃了多少块巧克力?
数据范围M ,N [1..10^9]
要求复杂度 时间O(log(M + N)) 空间O(1)

分析: 可以证明吃巧克力必然形成一个从0号开始的圈。因为0, M % N,  M * 2 % N .... 这些编号,如果有两个相等,比如a * M % N 和 b * M % N,满足0 < a < b 且a * M % N == b * M % N, 则有(b - a) * M % N == 0 ,说明再出现b * M % N 之前,已经出现了0。 于是问题等价于 求一个最小的正整数满足 x * M % N == 0 ,这样的x = N / gcd(M , N)。

// you can also use includes, for example:
// #include <algorithm>

int gcd(int x,int y) {
    return y?gcd(y, x % y):x;
}
int solution(int N, int M) {
    // write your code in C++98
    return N / gcd(M, N);
}

(2) 给定两个等长的整数数组,计算有多少(A【i】, B【i】) 包含的质因数种类相同?
数据范围:数组长度Z [1..6000],每个数的范围[1..2147483647]。
要求复杂度 时间 O(Z*(log(max(A【i】 + B【i】)) ^ 2), 空间 O(1)
分析: 假设g = gcd(A【i】, B【i】),我们下面要做的就是看A【i】 和B【i】是否和g包含相同的质因数。我们不断的求g‘ = gcd(A【i】, g),然后从A【i】中约掉g‘,当g‘ == 1的时候(互质),如果A【i】 == 1 就说明它们的质因数种类相同。这个时间复杂度怎么算?每次求gcd的时间复杂度 O(log(A【i】 + g)) = O(logA【i】), 要求多少次? 每次做出发A【i】至少一个质因数的指数减少1,所以最多循环的次数是A【i】里面所有质数的指数的和。于是最多循环次数是log(A【i】)次,所以求一组pair的时间复杂度在O((log(A【i】) ^ 2) + O(log(B【i】) ^ 2) 取max相加正好是要求的复杂度。
代码:

// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;

int gcd(int x,int y) {
    return y?gcd(y, x % y):x;
}

bool same(int x,int y) {
    for (; y > 1; ) {
        y = gcd(x, y);
        x /= y;
    }
    return (x == 1);
}

int solution(vector<int> &A, vector<int> &B) {
    // write your code in C++11
    int n = A.size(), answer = 0;
    for (int i = 0;  i < n; ++i) {
        int g = gcd(A【i】, B【i】);
        if (same(A【i】, g) && same(B【i】, g)) {
            ++answer;
        }
    }
    return answer;

}

更快的算法:
其实我们只要看A【i】的足够大次方 % B【i】 == 0  && B【i】的足够大次方 % A【i】 == 0即可。这是因为如果它们包含的质因数相同,一个的足够大次方(当指数足够大的时候)必然是另外一个的倍数。问题是“足够大”是多大?其实这个次方数是log级别的。当然算出这个足够大可以二分,也可以循环。模取幂也是log的复杂度,于是如果前面用二分的话,我们得到了一个单组的loglog的算法。但是我觉得这点没必要了,如果循环的话,我们得到的是log的算法。那不如我们直接取足够大为对方,更简单。即求A【i】 ^ B【i】 % B【i】 == 0 && B【i】 ^ A【i】 % A【i】 == 0,这肯定足够大了……注意模取幂是log的复杂度……
代码:

// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;

int mul(long long x,long long y,int m) {
    return x * y % m;
}

int powermod(int x,int y,int m) {
int r = 1 % m;
    for (; y ; y >>= 1) {
        if (y & 1) {
            r = mul(r, x, m);
        }
        x = mul(x, x, m);
    }
    return r;
}

int solution(vector<int> &A, vector<int> &B) {
    // write your code in C++11
int n = A.size(), answer = 0;
    for (int i = 0; i < n; ++i) {
        if ((powermod(A【i】, B【i】, B【i】) == 0) && (powermod(B【i】, A【i】, A【i】) == 0)) {
            ++answer;
        }
    }
    return answer;
}
时间: 2024-11-06 20:09:03

Codility上的练习 (10)的相关文章

codility上的问题 (36)Natrium 2014

这个题比较简单,好像也比较old,给定一个整数数组A,有N个元素,找到所有下标对(P,Q)满足  0 ≤ P ≤ Q < N 并且 A[P] ≤ A[Q]中最大的Q-P. 数据范围N [1..3*10^5] 数组元素[-10^9, +10^9] 要求时间复杂度O(N),空间复杂度O(N). 分析: 如果b[i] = max{a[i..N - 1]} ,则对每个i,我们找到最大的j,满足b[j]>=a[i],就可以了.这样做的目的是b,反映了后面还有没有比a[i]大的.注意到假如现在找到的最大差

codility上的问题(34) Fluorum 2014

好久没写codility的题了,一来没时间,二来有的题目不太好分析.这个题比较有意思,我还没有给出非常严格的证明. 给定一棵树(无向无环图),从一个节点出发,每次选择一个节点,从起点到目的节点的路径上没经过的节点尽可能多,直到遍历完所有的节点.如果起点到两个目的节点的路径中没经过的节点同样多,则选择标号较小的节点作为目的节点.如此继续,直到遍历所有的节点,求按顺序选择了哪些目的节点? 例如从2 开始,第一次选择0,然后1,0变为经历过的节点. 然后从0开始,第二次选择6, 然后4,6变为经历过的

android 127.0.0.1/localhost connection refused,在模拟器上应该用10.0.2.2访问你的电脑本机

调试中通过android simulator模拟器链接localhost或者127.0.0.1,因为我在电脑上面建立了apache,我的代码大概就是URL url = new URL(urlString);     URLConnection urlconn = url.openConnection(); 但是报错了!! Exception 1:java.net.ConnectException: localhost/127.0.0.1:8080 - Connection refused 问题是

Codility上的问题(35) Neon 2014

也是比较有意思的题,越来越数学了--不善于做这种题. 如图一个码头有N个木桩,用于拴住船,码头长度是M,可以理解未0到M的线段.有N调船,每条船的一半长度为X,所以船长是2 * X.每个船的中心必须拴在一个木桩上.并且每个木桩只能拴一条船.拴船的绳子长度是船的中心与木桩位置的距离.当然,木桩的位置不能移动,但是船可以自由左右移动.要求船头船尾必须都在码头上(0..M的线段),船也可以看作长度为2 * X的线段,请给每条船指定一个位置让拴船的最长绳子长度最短,求这个最短的绳子长度.如果无法容纳下所

RAC分解步骤之一,在oracle linux 4u4上安装oracle 10.2.0.1.0操作日志

练习oracle的rac组建过程,第一步,先练习4u4上安装oracle 10.2.0.1.0.直接安装rac,有些难度.从简单的做起.总RAC步骤,参照小布老师的RAC组建. 1. 启动vc,登陆vsphere 5.1 , 2. 新建一个虚拟机,Redhat 4 32bit 兼容的虚拟机,内存1G,硬盘30G.移除软驱,把光驱选择为ISO镜像文件. 3. 启动虚拟机,选择英文,选择美式键盘,选择custom,选择自己手动分区.分区为2个,一个swap,2100M,强制主分区,另一个为ext3,

世界上最疯狂10个建造中的摩天大楼

随着社会的发展,世界各地都在城市化进程中.众多的疯狂高楼建筑拔地而起,高楼的世界排名也在不断被刷新.包括上海中心大厦迪拜明珠.沙特王国塔.台北盘旋式摩天大楼.阿卜杜拉国王石油研究中心等等. 您可能感兴趣的相关文章 20幅精美绝伦光涂鸦摄影作品欣赏 35幅非常漂亮的夜景摄影作品欣赏 30幅震撼的精美高速摄影作品欣赏 15幅非常精美的影子摄影作品欣赏 25幅极具创意的倒影摄影作品欣赏 迪拜明珠 迪拜明珠是迪拜第一座没有梁柱的大厦,位于朱美拉棕榈岛对面, 可以眺望壮观的阿拉伯湾景色.里面将有一个能容纳

微信公开课上关于广告主10万粉丝要求的回应

微信公开课·广州站30日下午在小蛮腰广州塔举行,微信团队做了“开放不仅是一种态度,而且是能力”的演讲,并回答了广告主10万粉丝要求等一些微信公众号运营者关注的问题. Q:现在的广告主是针对10万以上的粉丝开放,对政府和媒体是不开放的.下一阶段会对媒体等行业进行开放吗? A:我们还在一个灰度测试期,会慢慢地把限制降低.比如,最近考虑过把10万的要求继续往下降,尽量让每一位都可以参与. Q:现在的微信小店要求有企业资质,而且非常严格,未来是否会开放个人认证的微信小店? A:从产品特性上来说,我们有过

在VirtualBox上安装Solaris 10全教程(包括下载)

您可以在博文的最下方留下评价, 也可以点击左边的 关注 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐 来支持一下喔 如果您对博文有任何疑问, 可以通过评论或发邮件的方式联系我: [email protected] 如需转载,请注明出处,谢谢合作!! 本篇随笔将详细讲解Solaris 10的下载和在VirtualBox上安装的全过程. 一.Solaris 10镜像下载 最近发现呀,这个Solaris 10的iso镜像是越来越难下载了,其实自从SUN公司给Orac

在Linux上使用的10种云备份方案

在Linux上使用的10种云备份方案 导读 不久前,为用户提供一种备份远程机器上数据的简易方法还很稀奇.现在,我们已觉得这理所当然.Dropbox及其他公司简化了这项任务.苹果.谷歌和微软都提供各自的数据备份方法. 在Linux上,情况有点不一样.发行版并不提供各自的云服务来管理你的数据(不过Ubuntu过去拥有Ubuntu One).一些主流发行版并不提供尚可的Linux客户软件. 但是你并非不走运.许多流行的服务确实可以在Linux下使用.你还有办法可以部署自己的解决方案,对数据获得控制权.