BZOJ1853/2393【容斥原理】

如果一个幸运数是另外的幸运数的倍数.那么做容斥的时候就不需要考虑它了.

/* I will wait for you*/

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <string>
#define make make_pair
#define fi first
#define se second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

const int maxn = 10010;
const int maxm = 1010;
const int maxs = 26;
const int inf = 0x3f3f3f3f;
const int P = 1000000007;
const double error = 1e-9;

inline ll read()
{
	ll x = 0, f = 1;
	char ch = getchar();
	while (ch <= 47 || ch >= 58)
		f = (ch == 45 ? -1 : 1), ch = getchar();
	while (ch >= 48 && ch <= 57)
		x = x * 10 + ch - 48, ch = getchar();
	return x * f;
}

ll top, n, num[maxn], vis[maxn];

ll gcd(ll a, ll b)
{
	return a ? gcd(b % a, a) : b;
}

ll dfs(int pos, int dir, ll sum)
{
	if (pos == top) {
		if (sum == 1)
			return 0;
		return (ll) (dir % 2 ? 1 : -1) * (n / sum);
	}

	if (vis[pos])
		return dfs(pos + 1, dir, sum);

	else {
		ll t = gcd(num[pos], sum), tmp = 0;

		tmp += dfs(pos + 1, dir, sum);

		if (sum / t <= n / num[pos])
			tmp += dfs(pos + 1, dir + 1, sum / t * num[pos]);
	
		return tmp;
	}
}

int main()
{
	for (int i = 10; i >= 1; i--)
		for (int j = (1 << i) - 1; j >= 0; j--) {
			for (int k = i - 1; k >= 0; k--) {
				if ((1 << k) & j)
					(num[top] *= 10) += 8;
				else
					(num[top] *= 10) += 6;
			}
			top++;
		}

	for (int i = 0; i < top; i++)
		for (int j = i + 1; j < top; j++)
			if (num[i] % num[j] == 0)
				vis[i] = 1;

	ll l = read(), r = read(), ans = 0;

	n = l - 1, ans -= dfs(0, 0, 1);
	n = r, ans += dfs(0, 0, 1);

	printf("%lld\n", ans);

	return 0;
}

你可能感兴趣的:(BZOJ1853/2393【容斥原理】)