BZOJ 1236: SPOJ1433 KPSUM

Posted 北屿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1236: SPOJ1433 KPSUM相关的知识,希望对你有一定的参考价值。

Description

用+-号连接1-n所有数字的数位,问结果是多少.

Sol

数位DP.

\(f[i][j][0/1][0/1]\) 表示长度为 \(i\) 的数字,开头数字是 \(j\) ,是否有前导0(这个会影响符号),每相邻两组数符号是否相同.

转移开一下代码吧.

这道题的符号有点乱,所以转移看起来有些乱...其实只有3个状态,没前导0,有前导0相邻两个数符号相同,有前导0相邻两个数符号不同.

没前导0的只有在第一次统计才会用到.

我发现自己写数位DP就是写小于 \(n\) 的,所有都需要将 \(n+1\) 计算...

一开始自己神tm的取了模...

Code

/**************************************************************
    Problem: 1236
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1308 kb
****************************************************************/
 
#include <cstdio>
#include <iostream>
using namespace std;
 
#define debug(a) cout<<#a<<"="<<a<<" " 
 
typedef long long LL;
const int N = 25;
 
LL n;
LL f[N][N][2][2];// i,j  0/1 qiandao0 0/1 fuhao
LL pow10[N];
 
void init() {
    pow10[0]=1;
    for(int i=1;i<=18;i++) pow10[i]=pow10[i-1]*10;
    for(int j=0;j<10;j++) {
        f[1][j][0][0]=f[1][j-1][0][0]+(j&1 ? 1 : -1)*j;
        f[1][j][1][0]=f[1][j][0][0];
        f[1][j][1][1]=f[1][j-1][1][1]-j;
    }
    for(int i=2;i<=18;i++) {
        f[i][0][0][0]=f[i-1][9][0][0];
        f[i][0][1][0]=-f[i-1][9][1][0];
        f[i][0][1][1]=-f[i-1][9][1][1];
        for(int j=1;j<10;j++) {
            f[i][j][0][0]=f[i][j-1][0][0]-f[i-1][9][1][!(i&1)]-(!(i&1))*j*pow10[i-1];
            f[i][j][1][0]=f[i][j-1][1][0]-f[i-1][9][1][0];
            f[i][j][1][1]=f[i][j-1][1][1]-f[i-1][9][1][1]-j*pow10[i-1];
        }
    }
     
/*  for(int i=1;i<=3;i++) {
        for(int j=0;j<10;j++) {
            cout<<i<<" "<<j<<":\n";
            for(int p=0;p<2;p++) for(int q=0;q<2;q++) debug(f[i][j][p][q]);
            cout<<endl;
        }
    }*/
}
LL calc(LL x) {
    LL g=0,r=0,v=0;
    for(int i=18;i;i--) {
        if(x/pow10[i-1]) {
            if(!g) {
                r+=f[i][x/pow10[i-1]-1][0][0];
                g=i;
            }else {
                r+=f[i][x/pow10[i-1]-1][1][!(g&1)]*((g-i)&1 ? -1 : 1);
            }
            if(g&1){
                if((x%pow10[i-1])&1) r+=x/pow10[i-1]*((g-i)&1 ? 1 : -1);
            }else {
                r+=x/pow10[i-1]*(x%pow10[i-1])*((g-i)&1 ? 1 : -1);
            }
        }x%=pow10[i-1];
    }return r;
}
int main() {
    init();
    cin>>n;
    cout<<calc(n+1)<<endl;
//  while(cin>>n) cout<<calc(n+1)<<endl;
    return 0;
}

 

以上是关于BZOJ 1236: SPOJ1433 KPSUM的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1433: [ZJOI2009]假期的宿舍

bzoj1433: [ZJOI2009]假期的宿舍

bzoj 1433: [ZJOI2009]假期的宿舍

网络流合集:bzoj1433,1934,1854 题解

bzoj1433[ZJOI2009]假期的宿舍(匈牙利)

bzoj 1433: [ZJOI2009]假期的宿舍