先收藏一个比较好的博客 http://www.cppblog.com/vici/archive/2011/09/05/155103.html
http://www.spoj.com/problems/SQFREE/
求1~n内不能被一个集合整除的数的个数。
简单的容斥原理,因为集合的个数 k <= 15,状态压缩一下,枚举每一个状态,根据其所含集合元素的个数进行加减。
复杂度(2^k*k*log x)
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
//#define LL long long
#define eps 1e-9
#define PI acos(-1.0)
using namespace std;
const int maxn = 100010;
long long n;
int k;
int a[20];
long long gcd(long long a, long long b)
{
if(b == 0)
return a;
else
return gcd(b,a%b);
}
long long lcm(long long a, long long b)
{
return a/gcd(a,b)*b;
}
int main()
{
while(~scanf("%lld %d",&n,&k))
{
for(int i = 0; i < k; i++)
scanf("%d",&a[i]);
long long ans = 0;
for(int i = 1; i < (1<<k); i++)
{
long long res = 1;
int cnt = 0;
for(int j = 0; j < k; j++)
{
if(i & (1<<j))
{
res = lcm(res,a[j]);
cnt++;
}
}
if(cnt & 1)
ans += n/res;
else
ans -= n/res;
}
printf("%lld\n",n-ans);
}
return 0;
}
hdu 1796 http://acm.hdu.edu.cn/showproblem.php?pid=1796
这题有坑,输入有可能为0,要把0的去掉。
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
//#define LL long long
#define eps 1e-9
#define PI acos(-1.0)
using namespace std;
const int maxn = 100010;
LL n;
int k,m;
int a[20];
LL gcd(LL a, LL b)
{
if(b == 0)
return a;
else
return gcd(b,a%b);
}
LL lcm(LL a, LL b)
{
return a/gcd(a,b)*b;
}
int main()
{
while(~scanf("%I64d %d",&n,&m))
{
k = 0;
for(int i = 0; i < m; i++)
{
scanf("%d",&a[i]);
}
for(int i = 0; i < m; i++)
{
if(a[i]) //a[i]为0的丢弃
a[k++] = a[i];
}
LL ans = 0;
for(int i = 1; i < (1<<k); i++)
{
LL res = 1;
int cnt = 0;
for(int j = 0; j < k; j++)
{
if(i & (1<<j))
{
res = lcm(res,a[j]);
cnt++;
}
}
if(cnt & 1)
ans += (n-1)/res;
else
ans -= (n-1)/res;
}
printf("%I64d\n",ans);
}
return 0;
}