牛客算法周周练1 - 幸运数字Ⅱ(预处理、DFS)

链接:https://ac.nowcoder.com/acm/contest/5086/E
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

定义一个数字为幸运数字当且仅当它的所有数位都是4或者7。
比如说,47、744、4都是幸运数字而5、17、467都不是。
定义next(x)为大于等于x的第一个幸运数字。给定l,r,请求出next(l) + next(l + 1) + ... + next(r - 1) + next(r)。

输入描述:

两个整数l和r (1 <= l <= r <= 1000,000,000)。

输出描述:

一个数字表示答案。

示例1

输入

2 7

输出

33
 
示例2

输入

7 7

输出

7

写法一:

明显一段区间内的next值是相同的。

我们可以通过预处理将可能的next值升序放在一个vector容器内,根据数据范围1e9,注意也要把4444444444放进去。

我们通过lower_bound(),查找容器中第一个大于等于 l 的位置。然后就可以通过幸运数字和 r 值之间的关系while就ok了。

 1 #include <bits/stdc++.h>
 2 typedef long long LL;
 3 #define pb push_back
 4 const int INF = 0x3f3f3f3f;
 5 const double eps = 1e-8;
 6 const int mod = 1e9+7;
 7 const int maxn = 1e5+10;
 8 using namespace std;
 9 
10 vector<LL> vt;
11 
12 void init()
13 {
14     for(int i=1;i<=9;i++)//找到一共有i位的所有幸运数字
15     {
16         for(int s=0;s<(1<<i);s++)//构造二进制数s,对应位上1代表数字7,0代表数字4
17         {
18             LL t = 0;
19             for(int j=i-1;j>=0;j--)//遍历每一位的时候注意要倒着来
20             {
21                 if((1<<j)&s) t=t*10+7;//对应位上是1,t末尾+7
22                 else t=t*10+4;//对应位上是0,t末尾+4
23             }
24             vt.pb(t);
25         }
26     }
27     vt.pb(4444444444);//根据数据范围,十位的只用考虑它一个,所以直接push_back
28 }
29 
30 int main()
31 {
32     #ifdef DEBUG
33     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
34     #endif
35     
36     init();
37     int l,r;
38     scanf("%d %d",&l,&r);
39     int pos = lower_bound(vt.begin(), vt.end(), l)-vt.begin();
40     LL ans = 0;
41     LL pre = l;//上一个幸运数字能解决到哪个数字
42     while(vt[pos]<=r)
43     {
44         ans+=(vt[pos]-pre+1)*vt[pos];//加上pre到此时的幸运数字之间的next值
45         pre=vt[pos]+1;//更新pre值为当前幸运数字+1
46         pos++;//下一个幸运数字
47     }
48     ans+=(r-pre+1)*vt[pos];//加上第一个比r小的幸运数字到r间的next值
49     printf("%lld\n",ans);
50     
51     return 0;
52 }

写法二:

由于每位只有两种选择,所以直接通过 DFS 预处理即可。

 1 #include <bits/stdc++.h>
 2 typedef long long LL;
 3 #define pb push_back
 4 const int INF = 0x3f3f3f3f;
 5 const double eps = 1e-8;
 6 const int mod = 1e9+7;
 7 const int maxn = 1e5+10;
 8 using namespace std;
 9 
10 LL a[maxn];
11 LL ans, l, r, cnt;
12 
13 void DFS(LL x)
14 {
15     if(x>r*10+4) return ;
16     if(x) a[++cnt]=x;
17     DFS(x*10+4);
18     DFS(x*10+7);
19 }
20 
21 int main()
22 {
23     #ifdef DEBUG
24     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
25     #endif
26     
27     scanf("%lld %lld",&l,&r);
28     DFS(0);
29     sort(a+1,a+1+cnt);
30     int pos = lower_bound(a+1, a+1+cnt, l)-a;
31     LL ans = 0;
32     LL pre = l;//上一个幸运数字能解决到哪个数字
33     while(a[pos]<=r)
34     {
35         ans+=(a[pos]-pre+1)*a[pos];//加上pre到此时的幸运数字之间的next值
36         pre=a[pos]+1;//更新pre值为当前幸运数字+1
37         pos++;//下一个幸运数字
38     }
39     ans+=(r-pre+1)*a[pos];//加上第一个比r小的幸运数字到r间的next值
40     printf("%lld\n",ans);
41     
42     return 0;
43 }

-

猜你喜欢

转载自www.cnblogs.com/jiamian/p/12741953.html
今日推荐