CF121A Lucky Sum(codeforces C++)

Petya喜欢Lucky Number。仅含有数字44和77的数字是一个Lucky Number。

规定next(x)next(x)等于最小的大于等于xx的Lucky Number。现在Petya想知道next(l)+next(l+1)+...+next(r-1)+next(r)next(l)+next(l+1)+...+next(r−1)+next(r)的值是多少。(1<=l<=r<=10^{9})(1<=l<=r<=109)


题目的意思就是只要含有4或7有其他数字就不行,除上一个幸运数字的前面,到本幸运数字

都赋值为这个幸运数字,详情请看这个图

 会输入两个访问输出这两个访问中间的所有值

这里最先想到的是用前缀和来处理,但是怎么去处理,这就很棘手,给的范围很大,我们也无法去一个一个判断幸运数字。到这里对幸运数字的寻找就显得特别重要4 和7先列一下幸运数字

4 7 44 47 74 77 444 447 474 477

不是4就是7看第一个和第三个的关系*10+4,再看第二个和第四个的关系*10+7

 	int t=3;
 	lucky[1]=4;                                 
	lucky[2]=7;
	for(int i=1;i<=2000;i++)
	{
		lucky[t++]=lucky[i]*10+4;
		lucky[t++]=lucky[i]*10+7;
	}
	

下一步对两个访问l,r的处理,我们唯一想的就是怎样把复杂度降到最低,对于l所对应的值是>=它的第一个幸运数(这里必是二分),对于r所对应的值为也是大于等于他的第一个幸运数,代码我想复杂了,我找的是小于等于他的最后一个数。对于前后边界特判处理一下就可以,对于中间的幸运数字不用前缀和,因为其特定区间内元素的值是相同的只需处理一下长度就行。

#include<iostream>
#include<algorithm> 
#include<cstring>
#include <cmath>
#include<vector>
#define PII pair<int><int>
#define ll long long 
#define endl "\n"
using namespace std;
const int N=1e5+10;
ll lucky[N];
ll sum=0,sum1,sum2;
ll x1,x2;
ll l,r;
ll RFl(int x)
{
	int l1=0,r1=2000;
	while(l1<r1)
	{
		ll mid=(l1+r1)>>1;
		if(x<=lucky[mid]) r1=mid;
		else l1=mid+1;
	}
	return l1;
 } 
 
 ll RFr(int x)
{
	int l1=0,r1=2000;
	while(l1<r1)
	{
		ll mid=(l1+r1+1)>>1;
		if(x>=lucky[mid]) l1=mid;
		else r1=mid-1;
	}
	return l1;
 }
void read_in()
{
	cin>>l>>r;
    
 } 
 void solve()
 {
 	int t=3;
 	lucky[1]=4;                                 
	lucky[2]=7;
	for(int i=1;i<=2000;i++)
	{
		lucky[t++]=lucky[i]*10+4;
		lucky[t++]=lucky[i]*10+7;
	}
	
	 x1=RFl(l),x2=RFr(r);
	
	if(x1==x2+1) //说明在同一区间 
	{
	   	sum=(r-l+1)*lucky[x1]; 
	}
	else
	{
     sum1=(lucky[x1]-l+1)*lucky[x1];
	 sum2=(r-lucky[x2])*lucky[x2+1];
	sum=sum1+sum2;
    int cha=x2-x1,k=x1;
    k++;
    while(cha--)
    {
    	sum+=(lucky[k]-lucky[k-1])*lucky[k];
    	k++;
	}
	 } 

 }
 void expert_out()
 {
 	cout<<sum;
 	//cout<<x1<<' '<<x2;
  } 
int main()
{
	read_in();
	solve(); 
	expert_out();
	return 0;
 } 

二分还得www.acwing.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值