标签:
这道题的主要解法在对1~100000000 中的luckNumber进行分块求和;
例如, luckSum[0] = Sum[1,4] luckSum[1] = Sum[5,7] luckSum[2] = Sum[8,44] ......................
然后根据l,r 的区间跨度来求和;
所在区间用一个int findUnder(int l)来求取;
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 1e9; ll luckNumber[1500][2]; ll luckSum[1500]; void init(){ int cnt=2; long long num; queue<long long> que; luckNumber[0][0]=1; luckNumber[0][1]=4; luckNumber[1][0]=5; luckNumber[1][1]=7; que.push(4); que.push(7); while(!que.empty()){ num = que.front(); que.pop(); if(num*10+4<=maxn) luckNumber[cnt][0] = luckNumber[cnt-1][1]+1,luckNumber[cnt++][1] = num*10+4,que.push(num*10+4); else break; if(num*10+7<=maxn) luckNumber[cnt][0] = luckNumber[cnt-1][1]+1,luckNumber[cnt++][1] = num*10+7,que.push(num*10+7); else break; } luckNumber[cnt][0]=luckNumber[cnt-1][1]+1; luckNumber[cnt][1]=4444444444; for(int i=0;i<cnt;i++){ luckSum[i] = (luckNumber[i][1]-luckNumber[i][0]+1)*luckNumber[i][1]; //cout<<luckSum[i]<<endl; } //cout<<cnt<<endl; } int findUnder(int l){ for(int i=0;i<=1022;i++){ if(l<=luckNumber[i][1]&&l>=luckNumber[i][0]) return i; } } int main(){ init(); int l,r,lSize,rSize; ll sum; scanf("%d%d",&l,&r); lSize = findUnder(l); rSize = findUnder(r); sum = 0; sum = (min(luckNumber[lSize][1],(ll)r)-l+1)*luckNumber[lSize][1]; for(int i=lSize+1;i<rSize;i++) sum+=luckSum[i]; if(lSize!=rSize){ sum += (r-luckNumber[rSize][0]+1)*luckNumber[rSize][1]; } printf("%I64d\n",sum); return 0; }
由cnt可以知道每次循环至多需要2^9次, 而至多只有5层循环 ,O(5*2^9);
Codeforces Beta Round #91 (Div. 1 Only) A. luckSum(区间分块求解)
标签:
原文地址:http://www.cnblogs.com/yuanshixingdan/p/5481508.html