• Luogu P2602 [ZJOI2010]数字计数


    这算是一道数位DP的入门题了吧虽然对于我来说还是有点烦

    经典起手式不讲了吧,(ans(a,b) o ans(1,b)-ans(1,a-1))

    我们首先预处理一个东西,用(f_i)表示有(i)位数字的时候,每个数字有几个(注意是和)。若不考虑前导零,则所有数字都是等价的,转移为:

    (f_i=10cdot f_{i-1}+10^{i-1})

    这个还是比较好理解的吧,前面一项表示无论这一位放什么直接从前面拿过来已有的,所以这一位可以放(0 o9)十个数,后面一项表示当这一位放上想要的数字时和前面得出的贡献。

    我们发现这样就很巧妙的避免了重复,因为前后两次计算刚好会产生多次贡献。

    然后考虑如何根据(f_i)推出答案。假设现在的数为(ABCD)

    和常规的数位DP一样,我们优先考虑首位对答案的共献,由于(1000,2000,...,A000)都小于等于(ABCD),可以直接加入贡献,所以我们将答案加上(Acdot f_3)即可。

    然后就是剩下的(A000 o ABCD)部分了,但是我们发现这个的求解过程就相当于(BCD)的贡献。

    所以我们成功将大问题分解,接下来就是继续算下一位的贡献了

    最后还有一个关于前导零的问题了,我们继续手玩一波

    当首位为(0)时,后面的(10^{i-1})位都是不合法的,以此类推,当前两位为(0)时,后面的(10^{i-2})位也不合法。

    因此(0)的贡献应该减去(sum_{i=0}^{len-1} 10^i)((len)表示数字位数)

    然后可喜可贺,终于做完了,上CODE吧

    #include<cstdio>
    #include<cctype>
    using namespace std;
    const int N=15;
    const long long pow[12]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000};
    long long a,b,c[10],d[10],f[N];
    int bit[N],cnt;
    inline char tc(void)
    {
        static char fl[100000],*A=fl,*B=fl;
        return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(long long &x)
    {
        x=0; char ch; while (!isdigit(ch=tc()));
        while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
    }
    inline void write(long long x)
    {
        if (x>9) write(x/10);
        putchar(x%10+'0');
    }
    inline void init(void)
    {
        for (register int i=1;i<=12;++i) f[i]=f[i-1]*10+pow[i-1];
    }
    inline void resolve(long long x)
    {
        cnt=0; while (x) bit[++cnt]=x%10,x/=10;
    }
    inline void solve(long long x,long long *num)
    {
        register int i,j; resolve(x);
        for (i=cnt;i>=1;--i)
        {
            for (j=0;j<bit[i];++j) num[j]+=pow[i-1];
            for (j=0;j<=9;++j) num[j]+=f[i-1]*bit[i];
            long long tot=0;
            for (j=i-1;j>=1;--j) tot=tot*10+bit[j];
            num[bit[i]]+=tot+1; num[0]-=pow[i-1];
        }
    }
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        register int i; read(a); read(b); init(); 
        solve(a-1,c); solve(b,d);
        for (i=0;i<=9;++i) write(d[i]-c[i]),putchar(' ');
        return 0;
    }
    
  • 相关阅读:
    带箭头提示框
    文本溢出显示省略号
    Git高级操作
    sublime text 2 破解
    python如何画三维图像?
    pytorch梯度下降法讲解(非常详细)
    pytorch数学运算与统计属性入门(非常易懂)
    pytorch张量数据索引切片与维度变换操作大全(非常全)
    pytorch中tensor张量数据基础入门
    pytorch深度学习神经网络实现手写字体识别
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9478157.html
Copyright © 2020-2023  润新知