记录一个菜逼的成长。。
ps:经典的容斥原理。当模板记录一下。
给你一个数n和有m个数,让你从1到n里去掉是m个数里至少一个数的倍数的数,问还剩下几个数。
根据容斥原理,如果选中的数是奇数个则要减去n/lcm,如果是偶数则要加上n/lcm
对于数是否选中可以状态压缩,用二进制来求。
这里我用的方法是反过来求。求的是1到n里是m个数里至少一个数的倍数的数的个数num,最后只要n-num就行了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cmath>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair
#define lowbit(x) (x)&(-x)
typedef long long LL;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int a[5];
LL lcm(LL a,LL b)
{
return a/__gcd(a,b)*b;
}
LL solve(LL n,LL m)///不超过m且能被n个数里至少一个数整除的不重复的个数
{
LL ans=0;
int i,j;
//枚举状态
for(i=1;i<(1<<n);i++){
LL mx=1,odd=0;
//判断有几个数被选中
for(j=0;j<n;j++){
if((1<<j)&i){
odd++;
mx=lcm(mx,a[j]);
}
}
if(odd&1)
ans+=m/mx;
else ans-=m/mx;
}
return ans;
}
int main()
{
a[0] = 2,a[1] = 3,a[2] = 5,a[3] = 7;
LL n;
while(~scanf("%lld",&n)){
printf("%lld\n",n - solve(4,n));
}
return 0;
}