codeforces 1424J,为了过这题,我把祖传的C++都用上了!
大家好,我们选择的是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++都用上了!的更多相关文章
- Codeforces#441 Div.2 四小题
Codeforces#441 Div.2 四小题 链接 A. Trip For Meal 小熊维尼喜欢吃蜂蜜.他每天要在朋友家享用N次蜂蜜 , 朋友A到B家的距离是 a ,A到C家的距离是b ,B到C ...
- You Are Given a Decimal String... CodeForces - 1202B [简单dp][补题]
补一下codeforces前天教育场的题.当时只A了一道题. 大致题意: 定义一个x - y - counter :是一个加法计数器.初始值为0,之后可以任意选择+x或者+y而我们由每次累加结果的最后 ...
- codeforces 1165F1/F2 二分好题
Codeforces 1165F1/F2 二分好题 传送门:https://codeforces.com/contest/1165/problem/F2 题意: 有n种物品,你对于第i个物品,你需要买 ...
- Codeforces 675C Money Transfers 思维题
原题:http://codeforces.com/contest/675/problem/C 让我们用数组a保存每个银行的余额,因为所有余额的和加起来一定为0,所以我们能把整个数组a划分为几个区间,每 ...
- Codeforces Gym 100531G Grave 水题
Problem G. Grave 题目连接: http://codeforces.com/gym/100531/attachments Description Gerard develops a Ha ...
- Codeforces 1137D - Cooperative Game - [交互题+思维题]
题目链接:https://codeforces.com/contest/1137/problem/D 题意: 交互题. 给定如下一个有向图: 现在十个人各有一枚棋子(编号 $0 \sim 9$),在不 ...
- Codeforces 767B. The Queue 模拟题
B. The Queue time limit per test:1 second memory limit per test:256 megabytes input:standard input o ...
- 多种方法过Codeforces Round #270的A题(奇偶法、打表法和Miller_Rabin(这个方法才是重点))
题目链接:http://codeforces.com/contest/472/problem/A 题目: 题意:哥德巴赫猜想是:一个大于2的素数一定可以表示为两个素数的和.此题则是将其修改为:一个大于 ...
- Codeforces 1205C Palindromic Paths (交互题、DP)
题目链接 http://codeforces.com/contest/1205/problem/C 题解 菜鸡永远做着变巨的梦 然而依然连div1BC题都不会做 要是那天去打cf怕是又要1题滚粗了.. ...
随机推荐
- vue+el-table在ajax分页时支持全选单页和全选所有
需求:el-table中,ajax分页的情况下,要支持全选单页和全选所有页中的记录,效果如下图所示: 界面代码: <el-table :data="tableDat ...
- Linux的进程、线程、文件描述符是什么
说到进程,恐怕面试中最常见的问题就是线程和进程的关系了,那么先说一下答案:在 Linux 系统中,进程和线程几乎没有区别. Linux 中的进程就是一个数据结构,看明白就可以理解文件描述符.重定向.管 ...
- DP百题练索引
就是一篇还在咕的文章 DP百题练(一) DP百题练(二) DP百题练(三)
- 洛谷 P2391 白雪皑皑 线段树+优化
题目描述: 现在有 \(N\) 片雪花排成一列. Pty 要对雪花进行$ M $次染色操作,第 \(i\)次染色操作中,把\((i*p+q)%N+1\) 片雪花和第\((i*q+p)%N+1\)片雪花 ...
- 微信小程序-TodoList
TodoList 博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020 作业要求 https://edu.cnblogs.com/campus/zjcsx ...
- 简单入门Rabbitmq
什么是RabbitMQ RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写.支持多种客户端,如:Python.Ruby..NET.Java.JMS.C.PHP.ActionScr ...
- 一些bug
长期留坑 1.AC自动机多模式串匹配问题 对于要统计各个模式串在文本中的出现次数,对于每个当前节点不能直接暴力跳$fail$ 复杂可以退化到$O(n^2)$ $aaaaaa--aaa$可以卡掉 要将$ ...
- C++ 设计模式 3:结构型模式
0 结构型模式 让类和类进行组合,获得更大的结构,获得新功能的方式. 1 代理模式 Proxy 模式又被叫做代理模式,是结构型的设计模式之一,它可以 为其他对象提供一种代理以控制对这个对象的访问. 所 ...
- Linux系统下用户如何膝盖FTP用户密码
其实修改ftp用户密码与修改普通用户的密码的过程是一眼高的其具体步骤如下 1.用root账户登录系统 2.使用passwd命令修改密码: 第一次输入密码后提示:The password fails t ...
- php 上传音频文件并获取时长
<input type="file" name="audio" id="voice_file" style="display ...