幸運數字
【題目描述】
在中國,很多人都把6和8視為是幸運數字!lxhgww也這樣認為,于是他定義自己的“幸運號碼”是十進制表示中只包含數字6和8的那些號碼,比如68,666,888都是“幸運號碼”!但是這種“幸運號碼”總是太少了,比如在[1,100]的區間內就只有6個(6,8,66,68,86,88),于是他又定義了一種“近似幸運號碼”。lxhgww規定,凡是“幸運號碼”的倍數都是“近似幸運號碼”,當然,任何的“幸運號碼”也都是“近似幸運號碼”,比如12,16,666都是“近似幸運號碼”。
現在lxhgww想知道在一段閉區間[a, b]內,“近似幸運號碼”的個數。
【輸入】
輸入數據是一行,包括2個數字a和b
【輸出】
輸出數據是一行,包括1個數字,表示在閉區間[a, b]內“近似幸運號碼”的個數
【樣例輸入1】
1 10
【樣例輸出1】
2
【樣例輸入2】
1234 4321
【樣例輸出2】
809
【數據范圍】
對于30%的數據,保證1<=a<=b<=1000000
對于100%的數據,保證1<=a<=b<=10000000000
//================================================================
用容斥原理做。
先造出所有的幸運號碼,然后對幸運號碼的倍數容斥。
幸運號碼有2000+個,為了盡快出解,要加幾個剪枝:
1. 如果A是B的倍數,直接去掉。剪掉了一大半。。。
2.從大到小排序,盡快容斥掉一些數。
寫的常數稍微少點能進2s了。。
PS :關于中間結果會爆long long的問題。。。從正的爆成負的容易,從正的爆成負的再爆成正的不容易。。。所以猥瑣的判大于0。。。
1
#include <iostream>
2
#include <algorithm>
3
#define NNUM 3000
4
#define ll long long
5
6
using namespace std;
7
8
ll A,B;
9
void Init()
{
10
scanf("%I64d%I64d",&A,&B);
11
}
12
13
int n = 0;
14
ll a[NNUM+1];
15
void dfsNum(ll num)
{
16
if (num > B) return;
17
if (num <= B)
18
a[++n] = num;
19
dfsNum(num * (ll)10 + (ll)6);
20
dfsNum(num * (ll)10 + (ll)8);
21
}
22
int cnt = 0;
23
ll b[NNUM+1];
24
25
ll Ans = 0, tmp;
26
inline ll gcd(ll a, ll b)
{
27
while (b)
28
tmp = a, a = b, b = tmp % b;
29
return a;
30
}
31
32
33
int cmp(const void *a, const void *b)
{
34
return (*(ll *)b) > (*(ll *)a) ? 1 : -1;
35
}
36
37
ll dfs(int pos, ll num)
{
38
if (pos == n+1) return B/num - A/num;
39
ll ret = dfs(pos+1, num);
40
ll newnum = num / gcd(num, a[pos]) * a[pos];
41
if (newnum <= B && newnum >= 1)
42
ret -= dfs(pos+1, newnum);
43
return ret;
44
}
45
46
void Solve()
{
47
dfsNum(6); dfsNum(8);
48
qsort(a+1, n, sizeof(a[0]), cmp);
49
//printf("%d\n",n);
50
for (int i = 1; i<=n; i++)
{
51
bool boo = true;
52
for (int j = 1; j<=n; j++)
53
if (i!=j && a[i] % a[j] == 0)
{
54
boo = false;
55
break;
56
}
57
if (boo)
{
58
a[++cnt] = a[i];
59
//printf("%d %I64d\n", cnt, a[cnt]);
60
}
61
}
62
n = cnt;
63
//printf("%d\n",n);
64
A--;
65
printf("%I64d\n", B - A - dfs(1,1));
66
}
67
68
int main()
{
69
freopen("luckynumber.in","r",stdin);
70
freopen("luckynumber.out","w",stdout);
71
Init();
72
Solve();
73
return 0;
74
}
75