容斥原理

1、原理

图来自Cloudddddd,
不想码字了,偷个图好了。。。


一共m个集合
我们将m用二进制表示,哪一位是1就代表有这个集合,0就代表没这个集合


2、代码模板:

#include<iostream>

using namespace std;

const int N=20;
typedef long long ll;

int n,m,p[N];

int main()
{
    scanf("%d %d",&n,&m);
    for(int i=0;i<m;i++)//输入m个质数
        scanf("%d",&p[i]);
    int res=0;//存答案
    for(int i=1;i<1<<m;i++)//按照二进制遍历所有的可能。枚举从1 到 1111...(m个1)的每一个集合状态, (至少选中一个集合)
    {
        int t=1,cnt=0;//t表示选中集合对应质数的乘积,cnt表示选中的集合数量
        for(int j=0;j<m;j++)//遍历0~m位,枚举当前状态的每一位
        {
            if(i>>j&1)//i右移j位,就是判断当前第j位是不是1
            {
                cnt++;//是1的话集合数就+1
                if((ll)t*p[j]>n)//如果乘积大于n,则n/t = 0, 跳出这轮循环
                {
                    t=-1;
                    break;
                }
                t*=p[j];//不大于就更新t
            }
        }
        if(t!=-1)//当不大于n时
        {
            if(cnt%2)   res+=n/t;//集合个数是奇数就加
            else        res-=n/t;//集合个数是偶数就减
        }
    }
    printf("%d",res);
    return 0;
}










全部评论

相关推荐

迷茫的大四🐶:哇靠,哥们,啥认证啊,副总裁实习,这么有实力嘛
一起聊美团
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务