题解 异或

传送门

容易发现 \(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;
}
posted @ 2021-09-13 18:26  Administrator-09  阅读(5)  评论(0编辑  收藏  举报