Java 由前n个自然数的二进制表示形式连接而成的数字的十进制值

Java 由前n个自然数的二进制表示形式连接而成的数字的十进制值,java,math,binary,mod,Java,Math,Binary,Mod,给定一个数字n,找出由前n个自然数的二进制表示形式串联而成的数字的十进制值。 以10^9+7为单位打印答案 此外,n可以大到10^9,因此需要对数时间方法 例:n=4,答案=220 解释:形成的编号=11011100(1=1,2=10,3=11,4=100)。 11011100=“220”的十进制值 下面我使用的代码只适用于第一个整数N注意,使用字符串表示法是不必要的(而且,在任务更改后也不有用)。看看位算术的方法(Python,但原理是一样的) 在关于模100000007的新条件下,我们只需在

给定一个数字n,找出由前n个自然数的二进制表示形式串联而成的数字的十进制值。
以10^9+7为单位打印答案

此外,n可以大到10^9,因此需要对数时间方法

例:n=
4
,答案=
220

解释:形成的编号=
11011100
1=1
2=10
3=11
4=100
)。
11011100
=
“220”
的十进制值


下面我使用的代码只适用于第一个整数N注意,使用字符串表示法是不必要的(而且,在任务更改后也不有用)。看看位算术的方法(Python,但原理是一样的)

在关于模100000007的新条件下,我们只需在每一步的结果计算行中添加模运算,因为左移和/或ing相当于2的幂乘和加法,这些运算遵循模性质的等价关系。请注意,中间结果不超过
100000007*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)

请注意,不需要使用字符串表示法(此外,在任务更改后也不有用)。看看位算术的方法(Python,但原理是一样的)

在关于模100000007的新条件下,我们只需在每一步的结果计算行中添加模运算,因为左移和/或ing相当于2的幂乘和加法,这些运算遵循模性质的等价关系。请注意,中间结果不超过
100000007*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)
cin>>n;
ll-ans=1;
ll 1=1;
对于(inti=2;i
cin>>n;
ll-ans=1;
ll 1=1;
对于(int i=2;i,这个问题需要
O(N)
时间。幸运的是,这可以在
O(logN)
时间内解决。另外,这是顺序:

1,6,27,220,1765,14126,113015,1808248,28931977, 462911642,7406586283,118505380540,1896086088653, 30337377418462,485398038695407,15532737238253040, 497047591624097297,15905522931971113522
顺序遵循此递归关系: 哪里⌊.⌋ 是

a(n)
也可以表示为倍数之和

如果我们对
a(14)
感兴趣,下面是它的计算方法

将上述方程两边的二次幂相乘,得到如下方程:

如果我们加上以上所有的方程,
a(14)
可以表示为四个
算术-几何级数之和。

需要注意的是,在除第一个序列外的所有序列中,算术级数的第一项是形式的,最后一项是形式的

算术-几何序列的n项之和可使用以下公式计算:

由于我们感兴趣的是
a(n)mod 100000007
,而不是实际的
a(n)
,这些模运算可能会派上用场

对于需要一些数论基础知识的除法模来说,这是一个很好的起点

一旦我们计算出所需序列的数量以及每个序列的五个变量
a、n、d、b、r
,就可以在
O(logn)
时间内计算出模100000007的
a(n)

下面是一个正在运行的
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;
}

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)
这个问题需要
O(N)
时间。幸运的是,这可以在
O(logN)
时间内解决。另外,这是顺序:

1,6,27,220,1765,14126,113015,1808248,28931977, 462911642,7406586283,118505380540,1896086088653, 30337377418462,485398038695407,15532737238253040, 497047591624097297,15905522931971113522
顺序遵循此递归关系: 哪里⌊.⌋ 是

a(n)
也可以表示为倍数之和

如果我们对
a(14)
感兴趣,下面是它的计算方法

将上述方程两边的二次幂相乘,得到如下方程:

如果我们加上以上所有的方程,
a(14)
可以表示为四个
算术-几何级数之和。

需要注意的是,在除第一个序列外的所有序列中,算术级数的第一项是形式的,最后一项是形式的

算术-几何序列的n项之和可使用以下公式计算:

由于我们感兴趣的是
a(n)mod 100000007
,而不是实际的
a(n)
,这些模运算可能会派上用场

对于需要一些数论基础知识的除法模来说,这是一个很好的起点

一旦我们计算出所需序列的数量以及每个序列的五个变量
a、n、d、b、r
,就可以在
O(logn)
时间内计算出模100000007的
a(n)

下面是一个正在运行的
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;
}

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)

您的值太大,无法存储在
Integer
中。请尝试更大的对象类,如
Long
。如果您想要无界缩放,请使用
biginger
。当更改为Long时,它将一直工作到18个整数
返回新的biginger(输入,2);
您的值太大,无法存储在
整数中。请尝试更大的对象类,如
Long
。如果您想要无界缩放,请使用
biginger
。当更改为Long时,它将一直工作到18个整数
返回新的biginger(输入,2)
既然连接很大,我们可以使用模10^9+7吗?这个条件彻底改变了问题。编辑问题是值得的。是的,我编辑了答案,检查结果是否与长算术一致。@MBo由于约束非常大,这种O(N)方法不可伸缩。存在O(logN) approach@duplex143但是作者并没有提到n约束,所以我不理解DV的原因,因为连接很大,我们可以使用模10^9+7吗?这个条件彻底改变了问题。值得编辑quest