spoj 6285. Another Game With Numbers(容斥)

先收藏一个比较好的博客   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;
}


你可能感兴趣的:(容斥原理)