![](/img/trans.png)
[英]I want to check if a number is binary or not in decimal numbers but it didnt work
[英]decimal value of the number formed by concatenating the binary representations of first n natural numbers
给定一个数字n ,找出通过连接前n 个自然数的二进制表示形成的数字的十进制值。
打印答案模 10^9+7。
此外, n可以大到 10^9,因此需要对数时间方法。
例如: n = 4
,答案 = 220
解释:形成的数字= 11011100
( 1=1
, 2=10
, 3=11
, 4=100
)。 十进制值11011100
= "220"
。
我在下面使用的代码仅适用于第一个整数N<=15
String input = "";
for(int i = 1;i<=n;i++) {
input += (Integer.toBinaryString(i));
}
return Integer.parseInt(input,2);
这个问题的解决方案需要O(N)
时间。 幸运的是,这可以在O(logN)
时间内解决。 此外,这是A047778序列:
1,6,27,220,1765,14126,113015,1808248,28931977, 462911642,7406586283,118505380540,1896086088653, 30337377418462,485398038695407,15532737238253040, 497047591624097297,15905522931971113522
该序列遵循这种递归关系: 其中⌊.⌋是楼层 function
a(n)
也可以表示为多个算术几何级数之和。
如果我们对a(14)
感兴趣,下面是它的计算方法。
在上述等式两边乘以 2 的幂得到如下等式:
如果我们将上述所有方程相加, a(14)
可以表示为four
算术-几何级数之和。
重要的是要注意,在除第一个序列之外的所有序列中,等差数列的第一项是形式 和最后一个学期
可以使用以下公式计算算术几何序列的 n 项之和:
a(First term of AP), n(Number of terms), d(Common Difference of AP), b(First term of GP), r(Common ratio of GP).
由于我们感兴趣的是a(n) mod 1000000007
而不是实际a(n)
项,因此这些模运算可能会派上用场。
这是实现除法模的一个很好的起点,它需要一些数论基础知识。
一旦我们计算出所需的序列数和每个序列的五个变量a, n, d, b, r
,就可以在O(logn)
时间内计算出a(n) modulo 1000000007
。
这是一个有效的C++
代码:
#include <numeric>
#include <iostream>
#define mod long(1e9+7)
long multiply(long a,long b){
a%= mod;b%= mod;
return (a*b)%mod;
}
void inverseModulo(long a,long m,long *x,long *y){ //ax congruent to 1 mod m
if(!a){
*x=0;
*y=1;
return ;
}
long x1,y1;
inverseModulo(m%a,a,&x1,&y1);
*x=y1-(m/a)*x1;
*y=x1;
return;
}
long moduloDivision(long a,long b,long m){ // (a*(returnValue))mod m congruent to b mod m
//https://www.geeksforgeeks.org/modular-division/ and https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
long x,y;
inverseModulo(b, m, &x, &y);
x%=m;
return (x*a)%m;
}
long power(long n,long r){ //calculates (n^r)%mod in logarithmic time
if(r==0) return 1;
if(r==1) return n;
if(r%2){
auto tmp=power(n, (r-1)/2);
return multiply(multiply(n,tmp),tmp);
}
auto tmp=power(n, r/2);
return multiply(tmp, tmp);
}
long sumOfAGPSeries(long a,long d,long b,long r,long n){
if(r==1) return multiply(n, multiply(a, 2)+multiply(n-1, d))/2;
long left=multiply(multiply(d, r), power(r,n-1)-1);
left=a+moduloDivision(left,r-1,mod);
left=multiply(left, b);
left%=mod;
long right=multiply(multiply(b, power(r, n)), a+multiply(n-1, d));
long ans=right-left;
ans=(ans%mod + mod) % mod;
return moduloDivision(ans,r-1,mod);
}
signed main(){
long N=1000;
long ans = 0;
long bitCountOfN = log2(N) + 1;
long nearestPowerOfTwo = pow(2, bitCountOfN - 1);
long startOfGP = 0;
while (nearestPowerOfTwo) { // iterating over each arithmetico–geometric sequence
long a, d, b, r, n;
a = N;
d = -1;
b = power(2, startOfGP);
r = power(2, bitCountOfN);
n = N - nearestPowerOfTwo + 1;
ans += sumOfAGPSeries(a, d, b, r, n);
ans %= mod;
startOfGP += n * bitCountOfN;
N = nearestPowerOfTwo - 1;
nearestPowerOfTwo >>= 1;
bitCountOfN--;
}
std::cout << ans << std::endl;
return 0;
}
可以使用这个简单的python
代码来验证上述C++
代码的有效性:
def a(n):
return int("".join([(bin(i))[2:] for i in range(1, n+1)]), 2)
for n in range(1,100):
print (a(n)%1000000007)
请注意,不需要使用字符串表示(此外,在任务更改后没有用处)。 使用按位算术查看方法(Python,但原理相同)
有了关于模 1000000007 的新条件,我们只需在每一步的结果计算行中添加模运算,因为左移和 or-ing 相当于乘以 2 的幂和加法,这些运算服从模性质的等价关系。 请注意,中间结果不超过1000000007*n
,因此long类型在这里适用于合理的 n 值。
n = 100
size = 0 #bit length of addends
result = 0 # long accumulator
for i in range(1, n + 1):
if i & (i - 1) == 0: #for powers of two we increase bit length
size += 1
result = ((result << size) | i) % 1000000007 #shift accumulator left and fill low bits with new addend
print(result)
没有按位运算的变体:
pow2 = 1
nextpow = 2
result = 0 # long accumulator
for i in range(1, n + 1):
if i == nextpow: #for powers of two we increase bit length
pow2 = nextpow
nextpow = nextpow * 2
result = (result * pow2 + i) % 1000000007 #shift accumulator left and fill low bits with new addend
cin>>n;
ll ans=1;
ll one=1;
for(int i=2;i<=n;i++)
{
ll digit=log2(i)+1;
ans=(((ans%N*(one<<digit)%N)%N+i%N)%N);
}
cout<<ans<<Ed;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.