1 条题解
-
0
自动搬运
来自洛谷,原作者为

WYXkk
Zzz Zzz搬运于
2025-08-24 22:16:44,当前版本为作者最后更新于2020-01-31 19:43:21,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
一般情况下,看到 等等毒瘤运算结合的时候,下面这个换元都会非常有效:
设 ,,,则 ,。
比如本题,采用以上换元,我们可以得到:,即 。
由于 ,所以 ,即 的二进制位被 的二进制位完全包含。
因此,我们枚举 ,对于每个 ,很显然有 个满足条件的 ,其中 表示 在二进制下为 的位的个数。
所以答案为 。
记 。
显然是可以 求的:(
ll代表long long,后面同理)inline ll f(ll n){if(!n)return 0;return f(n>>1)+n&1;}即,。
(代码中我使用了另一种实现方式)
由于我们有:
$$\begin{aligned}s(2n)&=\sum_{i=1}^{2n}2^{f(i)}\\&=\sum_{i=1}^n2^{f(2i-1)}+\sum_{i=1}^n2^{f(2i)}\\&=\sum_{i=1}^n2^{f(i-1)+1}+\sum_{i=1}^n2^{f(i)}\\&=2(1+\sum_{i=1}^{n-1}2^{f(i)})+\sum_{i=1}^n2^{f(i)}\\&=2+2s(n-1)+s(n)\\&=3s(n-1)+2^{f(n)}+2\end{aligned} $$因此我们就可以递归/倍增求 了。最后减去 即可。
#include<cstdio> #include<iostream> #include<fstream> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define Set(a) memset(a,0,sizeof(a)) #define F(i,a,b) for(register int i=a,i##end=b;i<=i##end;++i) #define UF(i,a,b) for(register int i=a,i##end=b;i>=i##end;--i) #define openf(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout) #define re register #define ri re int #define il inline typedef long long ll; typedef unsigned long long ull; template<typename T> inline T rd(T& x) { T f=1;x=0;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(T)(c-'0'); x*=f; return x; } ll rd(){ll x;rd(x);return x;} inline int max(int a,int b){return a>b?a:b;} inline int min(int a,int b){return a<b?a:b;} const int inf=1<<30; const ll p=1000000007; ll p2[70]; ll mod(ll t){return t>=p?t-p:t;} int bitc(ll x){int ans=0;while(x)x&=x-1,++ans;return ans;} ll f(ll n){return p2[bitc(n)];} ll sum(ll n) { if(n==0) return 0; if(n&1) return mod(sum(n^1)+f(n)); ll t=sum((n>>1)-1); return (3*t+f(n>>1)+2)%p; } int main() { p2[0]=1;F(i,1,64) p2[i]=mod(2*p2[i-1]); ll n; cin>>n; cout<<((sum(n)-n)%p+p)%p<<endl; return 0; }
- 1
信息
- ID
- 4019
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者