HDOJ7080Pty hates prime numbers(容斥原理)

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ7080Pty hates prime numbers(容斥原理)相关的知识,希望对你有一定的参考价值。

problem

Pty hates prime numbers
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 293 Accepted Submission(s): 87

Problem Description
Pty thinks prime numbers are extremely annoying numbers. Specifically, he hates the first k prime numbers.

As ”Hate me Hate my dog.” , if one prime factor of the integer x is what Pty hates, Pty will also hate x.

Now Pty wants to know how many integers in [1,n] he dosen’t hate.

Formally, Pty wants to know ∑nx=1[∀i∈[1,k],p[i]∤x] (p[i] means the ith prime number) .

Input
The first line contains a single integer T(1 ≤ T ≤ 100000) — the number of test cases

The only line of each test case contains two integers n,k(1 ≤ n ≤ 1018,1 ≤ k ≤ 16).

Output
For each test case, output the number of integers Pty doesn’t hate.

Sample Input
5
10 1
20 2
30 3
40 4
50 5

Sample Output
5
7
8
9
11

Source
2021“MINIEYE杯”中国大学生算法设计超级联赛(10)

Recommend
IceyWang | We have carefully selected several similar problems for you: 7099 7098 7097 7096 7095

solution

题意:

  • 给出n和k,求1-n中有多少个数不是前k个素数中的任意一个的倍数。
  • n <=1e18, k <= 16,T<=1e5

思路:

  • 不难想到容斥原理,二进制枚举,设枚举的乘积为x,去考虑前k个质数是否选择, 答案为 a n s + = n / x ∗ ( − 1 ) 形 成 x 质 数 的 个 数 ans+= n/x∗(−1)^{形成x质数的个数} ans+=n/x(1)x。 复杂度2^k,会超时。
  • 考虑优化,假设k==8,发现前8个素数的乘积为9699690,注意到如果数x不是前八个素数的倍数的话,那么x%9699690也不是前八个素数的倍数,所以我们可以预处理出1-9699690的答案,对于超过的部分让其==([n/9699690] + n%9699690)进行处理。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL m = 9699690;//2∗3∗5∗7∗11∗13∗17∗19
LL p[20] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};

vector<LL>a[18], b[18];//a,b表示前k个素数中选择偶数/奇数个能形成的数
void dfs(int x, LL y, int z, int k){
    if(x>k){
        if(z==1)a[k].push_back(y);//由偶数个素数组成
        else b[k].push_back(y);
        return ;
    }
    dfs(x+1, y,z,k);       //不使用第x个素数
    dfs(x+1,y*p[x], -z, k);//使用第x个素数
}
LL sum[m+10], as;
void init(){
    for(int k = 1; k <= 16; k++){//暴力前k个素数所能形成的乘积值
        if(k<=8)dfs(1,1,1,k);
        else dfs(9,1,1,k);
    }
    for(int i = 1; i <= 8; i++){ //标记1-m中可以被前8个数整除的数
        for(int j = p[i]; j <= m; j+=p[i]){
            sum[j] = 1;
        }
    }
    for(int i = 1; i <= m; i++){ //维护sum[i]表示1-i中不能被前8个数整除的数的个数
        sum[i] = sum[i-1]+(sum[i]==0);
    }
    as = sum[m];  //as表示1-9699690中不能被前8个数整除的数
}

int main(){
    init();
    int T;  cin>>T;
    while(T--){
        LL n, k;  cin>>n>>k;
        LL ans = 0;
        if(k <= 8){
            for(LL x : a[k])ans += n/x;
            for(LL x : b[k])ans -= n/x;
        }else{
            LL t;
            for(LL x : a[k])t=n/x, ans += (t/m)*as+sum[t%m];
            for(LL x : b[k])t=n/x, ans -= (t/m)*as+sum[t%m];
        }
        cout<<ans<<"\\n";
    }
    return 0;
}

以上是关于HDOJ7080Pty hates prime numbers(容斥原理)的主要内容,如果未能解决你的问题,请参考以下文章

hdoj1102 Constructing Roads(Prime || Kruskal)

hdoj 4548 美素数 打表

[HDOJ1754]I Hate It(分块)

2016 ACM/ICPC Asia Regional Shenyang Online && hdoj5901 Count primes Lehmer

hdoj1879 继续畅通工程(Prime || Kruskal)

hdoj1233 还是畅通工程(Prime || Kruskal)