Tim's Programming Space  
Tim's Programming Space
日历
<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678
统计
  • 随笔 - 20
  • 文章 - 1
  • 评论 - 40
  • 引用 - 0

导航

常用链接

留言簿(3)

随笔档案

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 

幸运数字

 

【题目描述】

在中国,很多人都把68视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字68的那些号码,比如68666888都是“幸运号码”!但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6866688688),于是他又定义了一种“近似幸运号码”。lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如1216666都是“近似幸运号码”。

现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。

【输入】

输入数据是一行,包括2个数字ab

【输出】

输出数据是一行,包括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
 6using namespace std;
 7
 8ll A,B;
 9void Init(){
10     scanf("%I64d%I64d",&A,&B);
11}

12
13int n = 0;
14ll a[NNUM+1];
15void 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}

22int cnt = 0;
23ll b[NNUM+1];
24
25ll Ans = 0, tmp;
26inline ll gcd(ll a, ll b){
27   while (b)
28         tmp = a, a = b, b = tmp % b;
29   return a;
30}

31
32
33int cmp(const void *a, const void *b){
34    return (*(ll *)b) >  (*(ll *)a) ? 1 : -1;
35}

36
37ll dfs(int pos, ll num){
38   if (pos == n+1return 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
46void 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!=&& 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
68int main(){
69    freopen("luckynumber.in","r",stdin);
70    freopen("luckynumber.out","w",stdout);
71    Init();
72    Solve();
73    return 0;
74}

75

posted on 2010-04-06 20:00 TimTopCoder 阅读(508) 评论(2)  编辑 收藏 引用
评论:
  • # re: SCTSC2010-幸运数字  rgt Posted @ 2010-04-12 20:50
    话说这道题可以分段打表。  回复  更多评论   

  • # re: SCTSC2010-幸运数字[未登录]  TimTopCoder Posted @ 2010-04-13 10:08
    @rgt
    orz。。。莫非sqrt一下?。。。  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


 
Copyright © TimTopCoder Powered by: 博客园 模板提供:沪江博客