CF83D [Numbers] 题解

Numbers

https://ac.nowcoder.com/acm/problem/109065

CF83D[numbers]

前言:

很好的一道数学容斥题。考察时间复杂度的分析。

2021/1/6 update: 因为笔者 , 一开始的做法比较劣(于是将题解重写了)

题意简述:

给定三个整数 ,, ()

你需要求出区间内,有多少个数 满足: && 不存在一个 使得

其中 表示 整除。

分析思路

我们发现一个很显然的性质。倘若 不是质数,那么最后的答案肯定是

为什么呢?

因为倘若 不是质数,假若 那么肯定存在一个不等于 的大于等于 的因子 也满足 ,这时候肯定没有一个满足条件的 ,所以最后答案是

因此我们只需要考虑 为质数的情况。

那么题意转化为:区间 中有多少个数 的最小质因数是

我们可以得到一个柿子:

= (其中 <= 并且 是一个质数。

对于柿子的解释:

表示对于 向下取整。

一开始的 就表示我们假设所有 的倍数的最小质因子都是 ,后面的 就是减去所有不合法的答案,也就是 的倍数中最小质因子不是 的数的个数。然后至于为什么 的括号里面是

实际上我们枚举的是 的倍数,也就是 乘上一个数,我们实际上只需要判断乘上的那个数的最小质因数大于等于 即可。

这里的 也就是乘上的数的范围啦!于是得到了这个柿子。

另外这道题目的一个技巧还有差分,也就是对于区间 算答案可以算 的答案 - 的答案。

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
bool GetPrime(int k) { //O(sqrt(n))判断质数相信大家都会
    for(int i = 2 ; i <= sqrt(k) ; i ++)
        if(k % i == 0) return 0;
    return 1;
}
int GetAns(int x,int k) { //上面提到的计算f(x,k)的函数
    if(GetPrime(k) == 0) return 0;//如果 k 不是质数,显然答案为0
    int sum = x / k;//假设全是k的倍数
    for(int i = 2 ; i <= min(x / k,k - 1) ; i ++)
        sum -= GetAns(x / k,i);
    return sum;
}
signed main() {
    int l , r , k ;
    cin >> l >> r >> k;
    cout << GetAns(r,k) - GetAns(l - 1, k);
    return 0;
}

短小,跑得飞快的!看得你是不是懵懵的?为什么这个玩意看起来这么暴力还这么快!

时间复杂度分析

关于这个时间复杂度的分析,由于是递归的形式,不妨按照类似于分析“搜索树”(这里指的是分析搜索复杂度的方法)的方式来按层分析,“搜索树”多少个点,时间复杂度就大概是多少。

考虑第一层向第二层的扩展: 大概会有 个扩张。

for(int i = 2 ; i <= min(x / k,k - 1) ; i ++)

这一行代码就告诉我们每一层最多就是循环

也就意味着第二层极限情况下大概会有 个扩张

第二层向第三层的扩张呢?有人可能会说是 个扩张,其实这么说是不严谨的,因为实际上,有很多点扩张实际上达不到 个。那么到底是多少呢?

不妨这么想,首先,考虑有多少个点只能扩展出 个,不难发现,有 是只能扩展出 个的 , 那么能扩展出 个的就是 ,那么按照这个趋势下去,实际上,我们发现对于扩展 个数的点,一共会有 个。
于是我们用这个规律来分析第二层向第三层一共有多少个扩展。

那么,对于第二层一共会有多少个扩展呢?

也就是 + + + + ...... +

现在我们的目标就是求出这里的 最大是多少。

不难得出,这里的 最大是 (在 的情况下) 那么上面的柿子我们就可以估算是

第三层向第四层的扩展呢?实际上这一层的扩展数量是很小的,在庞大的 面前,我们可以将其忽略不计(其实下面的层数大概把这个 乘以了一个 )。

因此,笔者估计总的复杂度大概就是 O(( + ) * 一个较小常数) 的。

不过上面分析的其实是程序最劣时间复杂度,实际上跑下来比这个要快得多。

闲人碎语 文章被收录于专栏

刊载算法学习笔记以及一些题解

全部评论
Orz 我只能跟着您的脚步来刷题
点赞 回复 分享
发布于 2021-01-06 21:55

相关推荐

有工作后先养猫:太好了,是超时空战警,我们有救了😋
点赞 评论 收藏
分享
4 收藏 评论
分享
牛客网
牛客企业服务