题解:P14074 [GESP202509 五级] 有趣的数字和
打表+枚举
题目大意
统计区间
思路分析
根据题意,使用如下的暴力枚举可以轻松通过 40% 的数据,但是剩余的数据,可能就TLE了。这是因为我们的枚举量太大,可能达到
ll ans=0;
for(ll i=l;i<=r;i++){
ll cnt=0,t=i;
while(t){
if(t&1) cnt++;
t>>=1;
}
if(cnt&1) ans+=i;
}
cout<<ans;
那要怎么优化呢?枚举优化的一个常见策略是打表,首先离线预处理一部分数据,存进数组里,后续计算时直接使用,减少枚举量。
结合本题数据规模分析,我们可以预处理计算出
根据前缀和的思想,还可以将本题
因此,可以使用如下代码预处理出
ll l=1,r=1e7,pre=0; // pre 保存前一个区间的和
while(r<=1e9+3e7){
ll ans=0;
for(ll i=l;i<=r;i++){
ll cnt=0,t=i;
while(t){
if(t&1) cnt++;
t>>=1;
}
if(cnt&1) ans+=i;
}
ans+=pre;
pre=ans;
cout<<ans<<",";
r+=1e7;
l+=1e7;
}
最后,使用这些预处理数据,拼凑答案即可。
即将
ll pre[]={0,24999997500000,...};// 打表
ll calc(ll n){
ll ans=0;
ll l=n/10000000*10000000;
for(ll i=l+1;i<=n;i++){
ll cnt=0,t=i;
while(t){
if(t&1) cnt++;
t>>=1;
}
if(cnt&1) ans+=i;
}
return ans+pre[n/10000000];
}
void solov(){
ll l,r;
cin>>l>>r;
cout<<calc(r)-calc(l-1);
}
AC Code
#include<bits/stdc++.h>/
#define quick_read ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long int ll;
ll pre[]={0,24999997500000,99999995000000,224999992500000,399999990000000,624999987500000,899999985000000,1225000052500000,1599999980000000,2025000067500000,2499999975000000,3025000082500000,3599999970000000,4224999967500000,4900000105000000,5624999962500000,6399999960000000,7224999957500000,8100000135000000,9024999952500000,9999999950000000,11024999947500000,12100000165000000,13224999942500000,14399999940000000,15625000187500000,16899999935000000,18225000202500000,19600000210000000,21024999927500000,22499999925000000,24024999922500000,25599999920000000,27225000247500000,28899999915000000,30624999912500000,32400000270000000,34225000277500000,36099999905000000,38024999902500000,39999999900000000,42025000307500000,44099999895000000,46225000322500000,48400000330000000,50624999887500000,52899999885000000,55225000352500000,57599999880000000,60025000367500000,62500000375000000,65024999872500000,67599999870000000,70225000397500000,72900000405000000,75625000412500000,78400000420000000,81225000427500000,84099999855000000,87025000442500000,89999999850000000,93025000457500000,96099999845000000,99224999842500000,102399999840000000,105624999837500000,108900000495000000,112224999832500000,115599999830000000,119025000517500000,122499999825000000,126025000532500000,129600000540000000,133224999817500000,136900000555000000,140624999812500000,144399999810000000,148224999807500000,152099999805000000,156025000592500000,159999999800000000,164024999797500000,168100000615000000,172225000622500000,176399999790000000,180625000637500000,184900000645000000,189224999782500000,193600000660000000,198024999777500000,202499999775000000,207025000682500000,211599999770000000,216225000697500000,220900000705000000,225625000712500000,230399999760000000,235225000727500000,240100000735000000,245025000742500000,250000000750000000,255025000757500000,260099999745000000,265225000772500000};
ll calc(ll n){
ll ans=0;
ll l=n/10000000*10000000;
for(ll i=l+1;i<=n;i++){
ll cnt=0,t=i;
while(t){
if(t&1) cnt++;
t>>=1;
}
if(cnt&1) ans+=i;
}
return ans+pre[n/10000000];
}
void solov(){
ll l,r;
cin>>l>>r;
cout<<calc(r)-calc(l-1);
}
int main(){
quick_read;
solov();
return 0;
}