C++ 求从1到n的数的所有二进制展开式之和

C++ 求从1到n的数的所有二进制展开式之和,c++,binary,C++,Binary,最近,我在一个竞争网站上遇到了一个问题,这是一个挑战。在那里,它被要求找出从1到n的数字的二进制表示的所有十进制解释的总和。假设当n=4时,总和为1+10+11+100=122。因为这个数字可能非常大,所以答案应该是模100000007。 我遇到了以下解决方案,但无法对其进行优化 #include<iostream> #include<queue> using namespace std; int Mod(string s, int a) { int res =

最近,我在一个竞争网站上遇到了一个问题,这是一个挑战。在那里,它被要求找出从1到n的数字的二进制表示的所有十进制解释的总和。假设当n=4时,总和为1+10+11+100=122。因为这个数字可能非常大,所以答案应该是模100000007。 我遇到了以下解决方案,但无法对其进行优化

#include<iostream>
#include<queue>
using namespace std;
int Mod(string s, int a)
{
    int res = 0, i, l = s.size();
    for( i = 0 ; i < l ; i++ )
    {
        res = ( res * 10 + s[i] - '0' ) % a;
    }
    return res;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        long long n;
        cin >> n;
        int Sum = 0, mod = 1000000007;
        queue<string> q;
        q.push("1");
        while( n > 0 )
        {
            n--;
            string s1 = q.front();
            q.pop();
            Sum = ( Sum + Mod(s1, mod) ) % mod;
            string s2 = s1;
            q.push(s1.append("0"));
            q.push(s2.append("1"));
        }
        cout << Sum << endl;
    }
    return 0;
}
#包括
#包括
使用名称空间std;
整数模(字符串s,整数a)
{
int res=0,i,l=s.size();
对于(i=0;i>t;
而(t--)
{
长n;
cin>>n;
整数和=0,模=100000007;
队列q;
q、 推送(“1”);
而(n>0)
{
n--;
字符串s1=q.front();
q、 pop();
Sum=(Sum+Mod(s1,Mod))%Mod;
字符串s2=s1;
q、 push(s1.append(“0”));
q、 推送(s2.附加(“1”));
}

cout在做了一些计算后,我终于想出了解决方案。感谢@maximum_prime_is_463035818提供了这些提示。以下是我的代码:

#include<iostream>
#include<cmath>
#define mod 1000000007
using namespace std;
long long power(long long x, long long y)
{
    long long res = 1LL;
    while(y)
    {
        if( y & 1LL )
        {
            res = ( res * x ) % mod;
        }
        y >>= 1LL;
        x = ( x * x ) % mod;
    }
    return res;
}
int main()
{
    long long t;
    cin >> t;
    while(t--)
    {
        long long n, i, l, m, s = 0;
        cin >> n;
        if( n && (!( n & ( n - 1LL ) )) )
        {
            l = ceil(log2(n)) + 1LL;
        }
        else
        {
            l = ceil(log2(n));
        }
        for( i = 0LL ; i < l ; i++ )
        {
        
            if( n & ( 1LL << i ) )
            {
                m = ( ( ( ( n / ( 1LL << ( i + 1LL ) ) ) * ( 1LL << i ) ) + 1LL ) + ( ( n % ( 1LL << ( i + 1LL ) ) ) % ( 1LL << i ) ) );
            }
            else
            {
                m = ( ( n / ( 1LL << ( i + 1LL ) ) ) * ( 1LL << i ) );
            }
            s = ( s + ( ( ( m % mod ) * power(10, i) ) % mod ) ) % mod;
        }
        cout << s << endl;
    }
    return 0;
}
#包括
#包括
#定义mod 100000007
使用名称空间std;
长功率(长x、长y)
{
长res=1L;
while(y)
{
如果(y&1LL)
{
res=(res*x)%mod;
}
y>>=1LL;
x=(x*x)%mod;
}
返回res;
}
int main()
{
长t;
cin>>t;
而(t--)
{
长n,i,l,m,s=0;
cin>>n;
如果(n&(!(n&(n-1LL)))
{
l=ceil(log2(n))+1L;
}
其他的
{
l=ceil(log2(n));
}
对于(i=0LL;i如果(n&(1LL)你想优化什么?运行时?内存使用?可读代码?我忘了提到时间限制。我已经编辑了它。它是1秒。因此,很明显,它是运行时。正确的解决方案不涉及实际相加,而是一个简单的数学公式。那就是“竞争网站”只是一个基于随机编程或数学技巧的无意义拼图列表。如果你不知道什么是你无法解决的诀窍。不幸的是,那些竞争性的网站不提供C++或编程指导,它们可以教你解决谜题所需的技巧。如果有人真的想学习C++,那就只有W。是的,他们会用一个。@Shashank实际上,这是数字二进制表示法的十进制解释之和。
10
在你的例子中,不是二的二进制表示法,而是十的十进制表示法。然后你需要更仔细地思考;)。当
n
为例如
15
时,则有
15/2
个数具有第一个位集,
15/4
个数具有第二个位集……诀窍就是迭代
2
的幂,而不是迭代
1
n