• 牛客小白月赛5 A 无关(relationship) 【容斥原理】【数据范围处理】


    题目链接:https://www.nowcoder.com/acm/contest/135/A

    题目描述 

      若一个集合A内所有的元素都不是正整数N的因数,则称N与集合A无关。

      给出一个含有k个元素的集合A={a1,a2,a3,...,ak},求区间[L,R]内与A无关的正整数的个数。
      保证A内的元素都是素数。

    输入描述:

    输入数据共两行:

    第一行三个正整数L,R,k,意义如“题目描述”。

    第二行k个正整数,描述集合A,保证k个正整数两两不相同。

    输出描述:

    输出数据共一行:

    第一行一个正整数表示区间[L,R]内与集合A无关的正整数的个数
    示例1

    输入

    复制
    1 10 4
    2 3 5 7

    输出

    复制
    1
    示例2

    输入

    复制
    2 10 4
    2 3 5 7

    输出

    复制
    0

    说明

    对于30%的数据:1<=L<=R<=10^6

    对于100%的数据:1<=L<=R<=10^18,1<=k<=20,2<=ai<=100


    题解:主要使用了容斥原理,但是在实现容斥原理代码中需要特殊考虑数值类型范围,处理爆范围情况。
     1 #include <cstdio>
     2 
     3 #define ll long long
     4 using namespace std;
     5 long long p[20];
     6 int k;
     7 
     8 ////容斥原理, solve 函数解出 [1,r] 中不包含 p 中所有因子的个数 
     9  long long  solve(unsigned long long r) {
    10     long long sum = 0;
    11     //共有 2^k 方钟组合
    12     for (int i = 1; i < (1 << k); ++i) {
    13          long long  mult = 1, bits = 0;
    14         for (int j = 0; j < k; ++j)
    15             if (i&(1 << j)) {//与i的二进制的第j位比较,看是否为1,是则选中
    16                 bits++;//计算i中1的个数,也就是质因数的个数
    17                 mult *= p[j];
    18                 //注意 Mult 会爆 long long ,
    19                 //超出范围最高为可能为0,也可能为1,在截断为 long long 型后,必须处理才能保证正确定
    20                 if (mult > r || mult < 0) mult = 0;
    21             }
    22         if (mult &&(bits & 1))//若1的个数是奇数则进行加法,否则进行减法
    23             sum += r / mult;
    24         else if(mult) sum -= r / mult;
    25     }
    26     return r - sum;//用总的数目-与n不互素的个数
    27 }
    28 
    29 
    30  //这种解法不需要处理爆 long long 的情况
    31 //long long solve(long long t) {
    32 //    int g = 1, i;
    33 //    long long temp1 = t;
    34 //    int count;
    35 //    while (g<(1<<k)) {
    36 //        count = 0;
    37 //        long long temp = temp1;
    38 //        for (i = 0; i < k; i++) {
    39 //            if (g&(1 << i)) {
    40 //                temp /= p[i];
    41 //                count++;
    42 //            }
    43 //        }
    44 //        if (count % 2 == 0) t += temp;
    45 //        else t -= temp;
    46 //        g++;
    47 //    }
    48 //    return t;
    49 //}
    50 
    51 int main()
    52 {
    53     long long l, r;
    54     int c = 0;
    55     scanf("%lld %lld %d", &l, &r, &k);
    56     for (int i = 0; i < k; i++)
    57     {
    58         scanf("%lld", &p[i]);
    59     }
    60 
    61     long long  flag = 1;
    62     for (int i = 0; i < k; i++) {
    63         if (l%p[i] == 0) flag = 0;
    64     }
    65     printf("%lld", solve(r) - solve(l) + flag);
    66     return 0;
    67 }
  • 相关阅读:
    关于以追加模式写入文件时,为什么第一行是空行?
    使用正则表达式的技巧
    super关键字的三种用法
    Excel快捷键
    重载与重写的区别
    方法重名
    区分子类方法中重名的三种变量
    继承
    Chapter08【String类、static、Arrays类、Math类】
    Math类
  • 原文地址:https://www.cnblogs.com/TianyuSu/p/9352313.html
Copyright © 2020-2023  润新知