Spoj SPOJ - KPSUM

数位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;
}


洛谷的SPOJ需要注册一个SPOJ账号并进行绑定才能进行交题。您可以按照以下步骤进行注册: 1. 打开洛谷网站(https://www.luogu.com.cn/)并登录您的洛谷账号。 2. 在网站顶部导航栏中找到“题库”选项,将鼠标悬停在上面,然后选择“SPOJ”。 3. 在SPOJ页面上,您会看到一个提示,要求您注册SPOJ账号并进行绑定。点击提示中的链接,将会跳转到SPOJ注册页面。 4. 在SPOJ注册页面上,按照要求填写您的用户名、密码和邮箱等信息,并完成注册。 5. 注册完成后,返回洛谷网站,再次进入SPOJ页面。您会看到一个输入框,要求您输入刚刚注册的SPOJ用户名。输入用户名后,点击“绑定”按钮即可完成绑定。 现在您已经成功注册并绑定了SPOJ账号,可以开始在洛谷的SPOJ题库上刷题了。祝您顺利完成编程练习!\[1\]\[2\] #### 引用[.reference_title] - *1* *3* [(洛谷入门系列,适合洛谷新用户)洛谷功能全解](https://blog.csdn.net/rrc12345/article/details/122500057)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [luogu p7492 序列](https://blog.csdn.net/zhu_yin233/article/details/122051384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值