• HDOJ3652解题报告【数位DP】


    题目地址:

      http://acm.hdu.edu.cn/showproblem.php?pid=3652

    题目概述:

      给出一个数n,求出1~n中所有包含“13”并且是13的倍数的数的个数。例如13满足条件,而143虽然是13的倍数,不过不包含“13”,所以不满足条件。

    大致思路:

      这种类型的题应该很容易看出是数位DP,这里设f[i,j,k,l]表示i位数当前位是j,这个数mod13=k的情况,l=1表示包含“13”,l=0表示不包含。

      转移的话详见代码。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <ctime>
    #include <map>
    #include <stack>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define sacnf scanf
    #define scnaf scanf
    #define scanfi(x) scanf("%d",&x)
    #define scanfd(x) scanf("%lf",&x)
    #define scanfl(x) scanf("%lld",&x)
    #define scanfc(x) scanf("%c",&x)
    #define scanfs(x) scanf("%s",&x)
    #define maxn  110
    #define maxm 10
    #define inf 1061109567
    #define Eps 0.00001
    const double PI=acos(-1.0);
    #define mod 1000000007
    #define MAXNUM 10000
    void Swap(int &a,int &b) {int t=a;a=b;b=t;}
    int Abs(int x) {return (x<0)?-x:x;}
    typedef long long ll;
    typedef unsigned int uint;
    
    int f[11][10][13][2];           //f[i,j,k,l]   i位数当前为是j,mod13=k的情况,l=1表示包含13
    int num[11];
    
    int power(int a,int b)
    {
        int ans=1;
        while(b)
        {
            if(b&1) ans*=a;
            a*=a;b>>=1;
        }
        return ans;
    }
    
    int calc(int x)
    {
        int cnt=0,ans=0,temp=0;
        while(x)
        {
            num[cnt++]=x%10;
            x/=10;
        }
        num[cnt]=0;bool flag=false;
        for(int i=cnt-1;i>=0;i--)
        {
            for(int j=0;j<num[i];j++)
            {
                ans+=f[i+1][j][(13-temp%13)%13][1];
                if(flag) ans+=f[i+1][j][(13-temp%13)%13][0];
                else if(j==3&&num[i+1]==1) ans+=f[i+1][j][(13-temp%13)%13][0];
            }
            if(num[i+1]==1&&num[i]==3) flag=true;
            temp+=num[i]*power(10,i);
        }
        return ans;
    }
    
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        //clock_t st=clock();
        int n;
        for(int i=0;i<10;i++) f[1][i][i][0]=1;
        for(int i=2;i<=10;i++)
        {
            for(int j=0;j<10;j++)
            {
                for(int k=0;k<10;k++)
                {
                    for(int l=0;l<13;l++)
                    {
                        f[i][j][(l+j*power(10,i-1))%13][1]+=f[i-1][k][l][1];
                        if(j==1&&k==3)
                        {
                            f[i][j][(l+j*power(10,i-1))%13][1]+=f[i-1][k][l][0];
                        }
                        else f[i][j][(l+j*power(10,i-1))%13][0]+=f[i-1][k][l][0];
    
                    }
                }
            }
        }
        while(~scanf("%d",&n))
        {
            int ans=calc(n+1);
            printf("%d
    ",ans);
        }
        //clock_t ed=clock();
        //printf("
    
    Time Used : %.5lf Ms.
    ",(double)(ed-st)/CLOCKS_PER_SEC);
        return 0;
    }
  • 相关阅读:
    Makefile 使用总结(转)
    linux,pthread(转)
    Java中this和super的用法总结
    「转」开发十年,只剩下这套Java开发体系了
    js的function立即执行函数
    什么是回调函数
    算法总结:双指针法的常见应用
    26. Remove Duplicates from Sorted Array
    1. Two Sum
    Spring的依赖注入和控制反转
  • 原文地址:https://www.cnblogs.com/CtrlKismet/p/6707750.html
Copyright © 2020-2023  润新知