zoukankan      html  css  js  c++  java
  • 数位DP

    由于学长的重重推荐DP很重要,最近一直刷DP

    刷到数位DP发现自己确实很不擅长这方面

    因此打算做一些总结:

    1.每次都是求前N个数,对于L~R的可以求前R减去前L

    2.对于前N个,可以先把每一位放到数组,跑一次dfs(f[x]代表,n的第x位

    3.对于dfs时候,分为两种:(1)是之前每一位都是与N的数相同(当前位所选的数不能超过f[x],只能遍历0~f[x])               只需要增设一个标记zt=1

                                        (2)是之前有过一位x所选的值低于f[x],那么现在无论如何选都不用怕超过N了,可以遍历0~9了                              zt=0

    4.对于dfs时,可以标记很多值,例如(1)求不能含有62的数,这时可以标记前一位是否是6

                                                   (2)求不能含有所有位之和能被7整除的,这时可以标记之前所有位%7的值

    5.对于dfs时,可以用数组记录一下,但是记录时只能记录zt==0时的值,需要初始化为-1,只有不为-1时才能直接输出(这里老忘写!=-1

    感觉一般都是一个 solve函数(处理出每一位)+dfs

    举个例子:hdu3652                                                                                                                                                                                                                (kuangbin专题真的好方便

    #include<stdio.h>
    #include<string.h>
    #define rep(i,j,k) for(long long i=j;i<=k;++i)
    long long dp[25][15][3][3];
    long long ff[24];
    long long f[25];
    long long dfs(long long x,long long sum,long long zt,long long is13,long long is1)
    {
        if(x==-1)
            return sum==0&&is13;
        if(!zt&&dp[x][(13-sum)%13][is13][is1]!=-1)
            return dp[x][(13-sum)%13][is13][is1];
        long long ans=0;
        if(zt)
        {
            ans=dfs(x-1,(sum+ff[x]*f[x])%13,1,is13||(is1&&f[x]==3),f[x]==1);
            rep(i,0,f[x]-1)
            ans=ans+dfs(x-1,(sum+ff[x]*i)%13,0,is13||(is1&&i==3),i==1);
        }
        else
        {
            rep(i,0,9)
            ans=ans+dfs(x-1,(sum+ff[x]*i)%13,0,is13||(is1&&i==3),i==1);
            dp[x][(13-sum)%13][is13][is1]=ans;
        }
        return ans;
    }
    long long solve(long long x)
    {
        long long len=0;
        while(x)
        {
            f[len++]=x%10;
            x=x/10;
        }
        return dfs(len-1,0,1,0,0);
    }
    int main()
    {
        ff[0]=1;
        rep(i,1,20)
        ff[i]=ff[i-1]*10;
        long long n;
        memset(dp,-1,sizeof(dp));
        while(scanf("%lld",&n)!=EOF)
        {
            printf("%lld
    ",solve(n));
        }
    }
    

      

  • 相关阅读:
    快速排序
    visio中相关设置菜单视图
    Visio中ShapeAdded和SelectionAdded
    VB托盘图标不响应WM_MOUSEMOVE的原因及解决方法
    visio应用程序相关设置选项视图
    直接插入排序的三种实现
    计算机存储的大小端模式解析
    直接选择排序及交换二个数据的正确实现
    用Apache Velocity模板引擎速造网站
    同一份代码打成多种包(JAR/WAR/EAR)时,如果不用classifier会产生什么有趣效果?
  • 原文地址:https://www.cnblogs.com/lmhyhblog/p/9420174.html
Copyright © 2011-2022 走看看