1031 无关(relationship) 容斥原理

链接:https://ac.nowcoder.com/acm/contest/26656/1031
来源:牛客网

题目描述

  若一个集合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

分析

 

典型的容斥原理题,先算出总数,再排除不符合条件的数的个数。

 n  / i 即可知道[0,n] 之间 i 的倍数的个数

ans = r / a1 + r / a2 + r / a3 + .... - r / a1 * a2 - r / a1 * a3 ........ + ........

奇数个数的倍数就 加上

偶数个数的倍数就 减去

通过状态压缩求每一种情况。

//-------------------------代码----------------------------

#define int ll
const int N = 3000;
int l,r,k;
int a[N];
int sum;
void solve()
{
    cin>>l>>r>>k;
    l -- ;
    for(int i = 0;i<k;i++) {
        cin>>a[i];
    }
    for(int i=1;i<(1<<k);i++){     
        int cnt = 0,res = 1;
        for(int j = 0;j<k;j++) {
            if(i & (1 << j)) {
                cnt ++ ;
                res *= a[j];//被选中的数的最小公倍数。
                if(res > r) break;
            }
        }
        if(cnt & 1) sum += r / res - l / res;
        else sum -= r / res - l / res;
    }
    cout<<r - l - sum<<endl;
}

signed main(){
    clapping();TLE;

//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-07-29 22:03  er007  阅读(51)  评论(0)    收藏  举报