CF598A Tricky Sum

题意:

该题目有多组数据,每组数据给出一个n,让你求出从1到n的和,但是其中每当遇到一个数是2的次幂时,就要变加为减。例如输入n=4,那么计算算式为-1-2+3-4=-4,因为1是2^0,2是2^1,4是2^2。共有t组数据。

  其实做法很简单,把从1到n的和用等差数列算出来,然后用log2n计算出不大于n的2的幂次共有多少个,用等比数列求和公式求出它们的和,减去两倍的它即可。

但是我发现WindowsXP居然卡精度严重,有很高的精度流失,

kepa=log(n)/log(2);当n=8时在Linux和Windows7下跑出来kepa都是3,

但WindowsXP跑出来居然是2,为了解决这个问题我们只能这样写kepa=(log(n)/log(2)+0.0000000001);

总体代码如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') p=-1,ch=getchar();
    while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar();
    return a*p;
}
ll t,n,kepa;
inline ll fast(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        
        if(b&1) ans*=a;
        a*=a;
        b>>=1;
    }
    return ans;
}
int main()
{
//    freopen("input","r",stdin);
//    freopen("output","w",stdout);
    t=read();
    while(t--)
    {
        n=read();
        kepa=(log(n)/log(2)+0.0000000001);
//        printf("%d",kepa);
        printf("%I64d\n",( (1ll+n)*n/2ll )-( (fast(2,kepa+1)-1ll)*2ll) );
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cold-cold/p/10023927.html
sum