Spoj SPOJ - KPSUM

来源:互联网 发布:linux查看内存占用前10 编辑:程序博客网 时间:2024/04/29 12:08

数位dp第一弹


#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<vector>#include<set>#include<map>#include<queue>#include<sstream>#include<string>#include<bitset>using namespace std;typedef long long LL;const LL LINF = (1LL <<63);const int INF = 1 << 31;const int NS = 500010;const int MS = 19;const int MOD = 1000000007;LL p10[22];void prepare(){    p10[0] = 1;    for(int i = 1; i < 22; i++)    {        p10[i] = p10[i - 1] * 10;    }}LL getSum1(int prelen, int suflen)//prelen >= 1, suflen >= 1;{    LL ans = 0;//    if(suflen <= 0) return 0;    if((prelen + suflen) & 1)    {        ans = -(p10[suflen] / 2);    }    else    {        if(suflen & 1)        {            ans = -(p10[suflen] * 9 / 2);        }    }    return ans;}LL checkSum1(int prelen, int suflen)//suflen >= 1;{    LL ans = 0;    int flag = 1;    LL lim = p10[suflen];    for(LL i = 0; i < lim; i++)    {        if(prelen & 1) flag = -flag;        for(int j = suflen - 1; j >= 0; j--)        {            int v = (i / p10[j]) % 10;            ans += flag * v;            flag = - flag;        }    }    return ans;}LL getSum2(LL prefix, int suflen)//prefix >= 1,  suflen >= 1{    LL presum = 0;    int prelen = 0;    int flag = 1;    for(LL x = prefix; x > 0; x /= 10)    {        prelen ++;        presum += (x % 10) * flag;        flag = - flag;    }    presum *= -flag;    LL ans = getSum1(prelen, suflen);    if(0 == ((prelen + suflen) & 1) )    {        presum *= p10[suflen];        ans += presum;    }    return ans;}LL getSum3(LL n){    LL ans = 0;    if(n < 10)    {        for(int i = 1; i <= n; i++)        {            ans += i * (0 == (i&1)? -1 : 1);        }        return ans;    }    int bitv[22];    int nlen = 0;    for(LL x = n; x > 0; x /= 10)    {        bitv[++nlen] = x % 10;    }    //计算 1 ~ 9999999(nlen 个 9)    ans = 5;    for(int suflen = 1; suflen < nlen - 1; suflen ++)    {        for(LL prefix = 1; prefix < 10; prefix ++)        {            ans -= getSum2(prefix, suflen);        }    }    LL prefix = 0;    LL presum = 0;    int flag = 1;    for(int pos = nlen; pos > 1; pos --)    {        for(int i = 0; i < bitv[pos]; i++)        {            if(0 != prefix)            {                ans -= getSum2(prefix, pos - 1);            }            prefix ++;        }        prefix *= 10;        presum += flag * bitv[pos];        flag = - flag;    }    int restnum = bitv[1] + 1;    if(nlen & 1)    {        if(restnum & 1)        {            ans -= presum;            ans -= bitv[1];        }        ans += restnum / 2;    }    else    {        ans -= presum * restnum;        ans += restnum * bitv[1] / 2;    }    return ans;}LL recoder, mark;void cal(LL x){    int bitv[22], len = 0;    for(LL t = x; t > 0; t /= 10)    {        bitv[len++] = t % 10;    }    for(int pos = len - 1; pos >= 0; pos --)    {        recoder += mark * bitv[pos];        mark = -mark;    }}int main(){    prepare();#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);//    freopen("out.txt", "w", stdout);#endif//    mark = 1; recoder = 0;//    for(LL i = 1; i < 10000000; i ++)//    {//        cal(i);////        if(i >= 101)//        {//            LL ans = getSum3(i);//            if(ans != recoder)//            {//                printf("i = %I64d recoder = %I64d ans = %I64d\n", i, recoder, ans);//                break;//            }//        }//    }    LL n;    while(~scanf("%lld", &n))    {        if(0 == n) break;        printf("%lld\n", getSum3(n));    }    return 0;}


0 0
原创粉丝点击