大家好,我们选择的是Bubble Cup比赛Div2场次的J题,不用问我Bubble Cup是什么比赛,我也不清楚。总之是一场算法比赛就是了。可能是这个比赛知名度比较低吧,参与的人数也不是很多,我们选择了一道中等通过人数的J题,作为今天的题目。

链接:https://codeforces.com/contest/1424/problem/J

这题非常不错,是一道质量很高的数学题,也很符合我的胃口。因为没有太多的trick,有的只有思维和逻辑的碰撞。

题意

我们都知道对于两个数a和b来说,我们可以很容易求到它们的最大公约数。我们假设a和b的最大公约数是k,如果 这三个数的长度可以构成一个合法的三角形,那么我们就认为a和b是互相友好的。

对于一个合法三角形而言,我们假设它的三条边长度分别是a,b,c,必须要有a + b > c, a + c > b, b + c > a,也就是任意两边之和大于第三边。这个应该是小学数学教的内容,大家应该都很了解。

如果在一个集合当中,某一个数找不到友好的数,那么就认为它是孤独的。现在我们给定一系列的n,表示1-n的自然数构成的集合,我们要求的是在这个集合当中孤独的数的数量。

样例

首先给定一个t(),表示测试数据的数量。

接着给定一行t个整数,表示不同的n()。对于每一个n,输出一个整数,表示1-n的自然数组成的集合当中孤独的数的数量。

n=5时,孤独数分别是1、3、5。n=10时,孤独的数分别是1、5、7.

题解

由于n的范围是1e6,所以是不可能接受的算法的,因此我们不可能枚举所有两个数构成的组合情况。所以暴力求解是行不通的,我们必须分析题目,得出其他的结论从而来简化问题。

首先我们很容易发现,1一定是孤独的。原因也简单,对于任意自然数x,它与1的最大公约数都是1。那么带来的结果就是1、1和x。由于x不能和1重复,所以x最小是2,但即使是2,也不满足1+1>2,所以一定无法构成三角形。所以不论n是多少,1一定都是孤独的。

另外比较容易想到的点就是互质的情况,假设a和b互质,也就是说它们的最大公约数是1。这样我们得到的三角形的三边就是1、a、b。同样a和b不相等,所以a和b至少相差1,所以也无法构成三角形的三边。所以如果两个数互相互质,那么一定不是友好的。从这点回过头来看,其实1之所以是孤独的,正是因为它与其他所有数都互质。

从这点出发我们又可以想到什么呢?

对了,可以想到质数。质数与其他所有自然数的最大公约数要么是1,要么是它本身。对于最大公约数是1的情况,我们已经分析过了,下面就来分析一下最大公约数是它本身的情况。我们假设这个质数是x,另外一个数是b,由于x和b的最大公约数是x,说明b是x的倍数。那么我们将b表示成kx。

这样我们得到的三角形三边分别是x、1、k。我们可以得到三个限制条件:

第三条是显然的,我们可以忽略, 我们仔细看下前面两条。我们把它们联立可以得到:,那么x只有一种取值就是。那么k有没有限制呢?k也是有限制的,k不能随便取值,我们需要保证,也就是,即。

通过这么一串分析我们得到了一个结论,对于一个质数x,它想要不是孤独的,必须要满足。反之也可以得到当的时候,且x为质数的时候,x一定是孤独的。

现在我们讨论完了质数的情况,但是对于合数的情况我们还不知道,那么会不会存在一些合数也是孤独的呢?其实是不会的,我们可以这样来证明。我们假设我们讨论的某个合数m,既然它是合数,那么它一定可以分解质因数。并且它一定可以分解出一个小于的质因数,证明过程也很简单,因为合数要么是平方数,要么拥有至少两个质因数。不论是这哪两种情况,只要它的质因数大于等于,那么它本身一定大于n。所以这就矛盾了。

既然合数一定可以找到一个小于的质因数,我们不妨假设这个质因数是x,合数m写成ax。a的范围应该是。那么我们要做的就是寻找一个数b,使得bx可以和ax构成友好,并且,且a和b互质,否则就不满足。

那么能不能找到这样的b呢?当然是可以的,而且非常非常简单。我们首先来分析一下我们要达成的条件,由于要使得三角形合法,我们需要达成的条件有4个:

通过前两个条件,我们可以得到b的范围。但是后面两个条件怎么办呢?其实很简单,我们可以分情况讨论,如果,那么我们可以选择b = a-1,这样的b一定满足条件。如果a < x,我们可以选择 b = x。由于x是质数,并且a < x,那么可以保证a和x一定互质。

这样,我们就证明了,所有的合数一定都不是孤独的,它们都可以找到自己的友好数。

所以,最终我们要求的就是大于的质数的数量,不过不要忘了再加上1,因为1也是满足条件的孤独数。由于n最大有,如果我们一个一个求质数肯定来不及,这里我们可以使用我们之前介绍过的埃式筛法来快速求取所有的质数。

还有一个问题是,我们要求某一个范围内的质数数量应该怎么办?其实很简单,我们只需要使用前缀和即可。

除了这些之外,这题还有一个坑点就是时间卡得很紧。以至于同样的算法Python实现的会超时,被逼无奈之下我只好用上了祖传的C++重写了一遍,总算是通过了。大家可以对比一下Python和C++的效率差距,还是挺可观的。

最后,附上代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include "time.h"
#include <functional>
// 一些宏定义
#define rep(i,a,b) for (int i=a;i<b;i++)
#define Rep(i,a,b) for (int i=a;i>=b;i--)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)
#define mid ((l+r)>>1)
#define lson (k<<1)
#define rson (k<<1|1)
#define MEM(a,x) memset(a,x,sizeof a)
#define L ch[r][0]
#define R ch[r][1]
using namespace std;
const int N=1000050;
const long long Mod=1000000007;
int t, query[N];
int isprime[N], primecnt[N];

// 埃式筛法
void eratosthenes() {
    rep(i, 0, N) isprime[i] = 1;
    rep(i, 2, N) {
        if (isprime[i]) {
            for (int j = i+i; j < N; j += i) {
                isprime[j] = 0;
            }
        }
    }
    // 维护质数的前缀和
    rep(i, 2, N) {
        primecnt[i] = primecnt[i-1] + isprime[i];
    }
}

int main() {
    eratosthenes();
    scanf("%d", &t);
    rep(i, 0, t) {
        int query;
        scanf("%d", &query);
        printf("%d\n", primecnt[query] - primecnt[int(sqrt(query))] + 1);
    }
    return 0;
}

今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发

{{uploading-image-742109.png(uploading...)}}

codeforces 1424J,为了过这题,我把祖传的C++都用上了!的更多相关文章

  1. Codeforces#441 Div.2 四小题

    Codeforces#441 Div.2 四小题 链接 A. Trip For Meal 小熊维尼喜欢吃蜂蜜.他每天要在朋友家享用N次蜂蜜 , 朋友A到B家的距离是 a ,A到C家的距离是b ,B到C ...

  2. You Are Given a Decimal String... CodeForces - 1202B [简单dp][补题]

    补一下codeforces前天教育场的题.当时只A了一道题. 大致题意: 定义一个x - y - counter :是一个加法计数器.初始值为0,之后可以任意选择+x或者+y而我们由每次累加结果的最后 ...

  3. codeforces 1165F1/F2 二分好题

    Codeforces 1165F1/F2 二分好题 传送门:https://codeforces.com/contest/1165/problem/F2 题意: 有n种物品,你对于第i个物品,你需要买 ...

  4. Codeforces 675C Money Transfers 思维题

    原题:http://codeforces.com/contest/675/problem/C 让我们用数组a保存每个银行的余额,因为所有余额的和加起来一定为0,所以我们能把整个数组a划分为几个区间,每 ...

  5. Codeforces Gym 100531G Grave 水题

    Problem G. Grave 题目连接: http://codeforces.com/gym/100531/attachments Description Gerard develops a Ha ...

  6. Codeforces 1137D - Cooperative Game - [交互题+思维题]

    题目链接:https://codeforces.com/contest/1137/problem/D 题意: 交互题. 给定如下一个有向图: 现在十个人各有一枚棋子(编号 $0 \sim 9$),在不 ...

  7. Codeforces 767B. The Queue 模拟题

    B. The Queue time limit per test:1 second memory limit per test:256 megabytes input:standard input o ...

  8. 多种方法过Codeforces Round #270的A题(奇偶法、打表法和Miller_Rabin(这个方法才是重点))

    题目链接:http://codeforces.com/contest/472/problem/A 题目: 题意:哥德巴赫猜想是:一个大于2的素数一定可以表示为两个素数的和.此题则是将其修改为:一个大于 ...

  9. Codeforces 1205C Palindromic Paths (交互题、DP)

    题目链接 http://codeforces.com/contest/1205/problem/C 题解 菜鸡永远做着变巨的梦 然而依然连div1BC题都不会做 要是那天去打cf怕是又要1题滚粗了.. ...

随机推荐

  1. kube-proxy实现原理

    1.service概念 service是一组pod的服务抽象,相当于一组pod的LB,负责将请求分发给对应的pod.service会为这个LB提供一个IP,一般称为cluster IP.kube-pr ...

  2. Runnable接口和Callable接口的区别

    Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已:Callable接口中的call()方法是有返回值的,是一个泛型,和Future.Fut ...

  3. 测试流程规范--测试准入、准出、停止标准、bug优先级定义

    一.背景 最近在推进组内流程规范专项建设,从"研发测试流程"."提测规范"."测试准入标准"."bug优先级标准".&q ...

  4. K8S Canal基于Prometheus进行实时指标监控

    文章来源于本人的印象笔记,如出现格式问题可访问该链接查看原文 部署canal的prometheus监控到k8s中 1.grafana的docker部署方式:https://grafana.com/gr ...

  5. Java_静态代理与Lambda

    静态代理 要点: 公共接口 真实角色 代理角色 public class StaticProxy { public static void main(String[] args) { You you ...

  6. 凝思磐石安全系统V6.0.8版本(debian)增加多于4个串口方法

    在网上找了好多方法,大家基本上都用ubuntu系统做实现演示,里面的有些文件我在凝思系统上根本找不到,最终通过摸索已解决,记录下操作过程(整个过程都需要在root用户下进行): 判断系统目前能识别的串 ...

  7. Hadoop2.6伪分布式按照官网指点安装(1)

    参考:http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/SingleCluster.html 照抄:安装成功 ...

  8. [MIT6.006] 23. Computational Complexity 计算复杂度

    这节课主要讲的计算复杂度,一般有三种表达不同程度的计算复杂度,如下图所示: P:多项式时间: EXP:指数时间: R:有限时间内. 上图还给了一些问题的计算复杂度的对应结果,关于一些细节例如NP, N ...

  9. K-近邻算法kNN

    K-近邻算法(k-Nearest Neighbor,简称kNN)采用测量不同特征值之间的距离方法进行分类,是一种常用的监督学习方法,其工作机制很简单:给定测试样本,基于某种距离亮度找出训练集中与其靠近 ...

  10. Linux杂谈: 实现一种简单实用的线程池(C语言)

    基本功能 1. 实现一个线程的队列,队列中的线程启动后不再释放: 2. 没有任务执行时,线程处于pending状态,等待唤醒,不占cpu: 3. 当有任务需要执行时,从线程队列中取出一个线程执行任务: ...