P14074 [GESP202509 五级] 有趣的数字和 题解

题目描述

如果一个正整数的二进制表示包含奇数个 1,那么小 A 就会认为这个正整数是有趣的。

例如,7 的二进制表示为 (111)2​,包含 1 的个数为 3 个,所以 7 是有趣的。但是 9=(1001)2​ 包含 2 个 1,所以 9 不是有趣的。

给定正整数 l,r,请你统计满足 l≤n≤r 的有趣的整数 n 之和。

输入格式

一行,两个正整数 l,r,表示给定的正整数。

输出格式

一行,一个正整数,表示 l,r 之间有趣的整数之和。

输入输出样例

输入 #1复制运行

3 8

输出 #1复制运行

19

输入 #2复制运行

65 36248

输出 #2复制运行

328505490

说明/提示

【数据范围】

对于 40% 的测试点,保证 1≤l≤r≤10^{4}

对于另外 30% 的测试点,保证 l=1 并且 r=2^{k}−1,其中 k 是大于 1 的正整数。

对于所有测试点,保证 1≤l≤r≤10^{9}

【提示】

由于本题的数据范围较大,整数类型请使用 long long。

代码1(40%分数)

#include <bits/stdc++.h>
using namespace std;
bool f(int x){
	long long s=0;
	while(x>0){
		char c=x%2+'0';
		x/=2;
		if(c=='1'){
			s++;
		}
	}
	if(s%2==0){
		return false;
	}
	else{
		return true;
	}
}
int main(){
	long long l,r;
	cin>>l>>r;
	long long ans=0;
	for(int i=l;i<=r;i++){
		if(f(i)==true){
			ans+=i;
		}
	}
	cout<<ans;
	return 0;
}

代码2(70%分数)

#include <bits/stdc++.h>
using namespace std;
bool f(int x){
    long long s=0;
    while(x>0){
        s+=x%2;
        x/=2;
    }
    return s%2;
}
int main() {
    long long l,r;
    cin>>l>>r;
    long long ans=0;
    if (r<=1e4){
        for(int i=l;i<=r;i++){
            if (f(i)){
                ans+=i;
            }
        }
        cout<<ans;
        return 0;
    }
    cout<<(r+1)*r/4;
    return 0;
}

AC代码(100%分数)

#include<bits/stdc++.h>
using namespace std;
long long a[1005]={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};
long long c(long long n){
	long long ans=0;
	long long l=n/10000000*10000000;
	for(long long i=l+1;i<=n;i++){
		long long z=0,v=i;
		while(v){
			if(v&1) z++;
			v>>=1;
		}
		if(z&1) ans+=i;
	}
	return ans+a[n/10000000];
}
int main(){
	long long n,m;
	cin>>n>>m;
	cout<<c(m)-c(n-1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值