题解 异或
容易发现 \(i \oplus i+1\) 的值大概长这样:
i: 0^1 1 000001
i: 1^2 3 000011
i: 2^3 1 000001
i: 3^4 7 000111
i: 4^5 1 000001
i: 5^6 3 000011
i: 6^7 1 000001
i: 7^8 15 001111
i: 8^9 1 000001
i: 9^10 3 000011
i: 10^11 1 000001
i: 11^12 7 000111
i: 12^13 1 000001
i: 13^14 3 000011
i: 14^15 1 000001
i: 15^16 31 011111
i: 16^17 1 000001
i: 17^18 3 000011
i: 18^19 1 000001
i: 19^20 7 000111
发现可以以2的次幂为界进行划分
倍增处理即可
复杂度 \(O(logn)\)
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define reg register int
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
ll n;
namespace force{
ll ans;
void solve() {
for (int i=0; i<n; ++i) {
//cout<<"i: "<<i<<'^'<<i+1<<' '<<(i^(i+1))<<' '<<bitset<6>(i^(i+1))<<endl;
int s=i^(i+1);
do {++ans; s&=s-1;} while (s);
}
printf("%lld\n", ans);
exit(0);
}
}
namespace task1{
ll f[80], base, pos, ans;
void solve() {
f[0]=1;
for (base=1; (1ll<<base)<=n; ++base)
f[base]=f[base-1]<<1|1;
--base;
//for (int i=0; i<=5; ++i) cout<<f[i]<<' '; cout<<endl;
pos=(1ll<<base)-1;
ans=f[base];
//cout<<"ans: "<<ans<<endl;
//cout<<"base: "<<base<<endl;
//cout<<"pos: "<<pos<<endl;
for (int i=base; ~i; --i)
if (pos+(1ll<<i)<n) {
ans+=f[i], pos+=1ll<<i;
//cout<<"i: "<<i<<endl;
}
printf("%lld\n", ans);
exit(0);
}
}
signed main()
{
n=read();
//force::solve();
task1::solve();
return 0;
}