牛客算法周周练1 - 幸运数字Ⅱ(预处理、DFS)
链接:https://ac.nowcoder.com/acm/contest/5086/E
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制: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)。
比如说,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 }
-