首先引用一下大佬的博客
推一下为什么是这样的:
首先:当二进制是满1的话就是
∑
i
=
0
x
a
i
=
(
1
+
c
)
n
\sum_{i=0}^{x}a_{i} = (1+c)^{n}
∑i=0xai=(1+c)n其中
n
n
n为
x
x
x的二进制位数,这个其实很容易就能看出来吧按我的思路说一下:相当于一共
n
n
n位在
n
n
n位取小于等于
n
n
n个1其实就是组合数
C
n
0
∗
c
0
+
C
n
1
∗
c
1
+
.
.
.
+
C
n
n
∗
c
n
=
(
1
+
c
)
n
C_{n}^{0}*c^{0}+C_{n}^{1}*c^{1}+...+C_{n}^{n}*c^{n} = (1+c)^{n}
Cn0∗c0+Cn1∗c1+...+Cnn∗cn=(1+c)n也就是上面那个所以我们进而在满二进制为1的
x
x
x上+上1那么就是变成了一个
2
x
+
1
2^{x+1}
2x+1的形式,求这个的话我们可以分为两种:
- 第一种就是二进制最高位为1,他就相当与多了一位为1,这样他就会导致次方数x+1(也就是选择放1的地方多了一个当然是在原基础上也就是不会大于那个极限值),也就是 c ∗ a n s c*ans c∗ans(第一次出现ans为1)
- 第二种就是二进制最高位为0,那么他其实转化成了上一位满1的那种情况
所以总的就是这两种的和
在推广一下:直接就是上面那个吧。
其实就能看出递归式:
ans = (qpow(1+c,len-i-1)+c*ans%mod)%mod;
总的代码是这样的:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long mod=1e9+7;
ll qpow(ll a,ll b) {
ll sum=1;
while(b) {
if(b&1) sum=sum*a%mod;
b>>=1;
a=a*a%mod;
}
return sum;
}
int main() {
string str;
cin>>str;
ll c;
cin>>c;
ll sum=1;
ll len=str.size();
for(int i=len-1; i>=0; i--) {
if(str[i]=='1')
sum=(qpow(1+c,len-i-1)+c*sum%mod)%mod;
}
cout<<sum<<endl;
return 0;
}
还有一种类型(第一开始理解的类型还没调对,可以看着这个理解上面那个):
另一种形式