概念

Transclude of 数学#^193df4

时间复杂度

由组合数证明:

即在组合里挑1,挑2,挑3来做计算 即

应用

要挑选1-n中可以被所给质数整除的数的数量

判断是并集,是能被一个质数整除的数的集合并集之后的数量

用容斥原理 将每个集合的数量用 n/p 下取整表示(即能整数的数的数量) 只要选定一个p,就可以用上述公式算出其集合数量,再利用容斥原理相加可以得到最终数量

int main()
{
    int n, m;
    cin >> n >> m;
    
    
    int p[N];
    for(int i = 0; i < m; i ++)
    {
        cin >> p[i];
    }
    
    LL ans = 0;
    
    //挑1-m中的质数,选中整除数的集合
    for(int i = 1; i < 1 << m; i ++)
    {
        LL t = 1, cnt = 0;
        for(int j = 0; j < m; j ++)
            if(i >> j & 1) // 判断哪个位置上有1
            {
                cnt ++;
                //判断当前选中的数是否都可以被n整除,不可以就不用算了
                if(t * p[j] > n)
                {
                    t = -1;
                    break;
                }
                t *= p[j];
            }
            
        if(t != -1) 
        {
            if(cnt % 2)  ans += n / t;
            else ans -= n / t;
        }
    }
    
    cout << ans << endl;
    
    return 0;
}

这里运用了一些技巧

要挑选组合数,可以利用位运算来简化

将一组数模拟为一串01串,如果是1,就说明该数被挑选,这样恰可以表示出所有可能的情况

再利用位运算 if(i >> j & 1) 可以判断某一位上是否是1