zoukankan      html  css  js  c++  java
  • B-number HDU

    讲数位DP讲的很好的一篇博客:https://blog.csdn.net/wust_zzwh/article/details/52100392#commentsedit

    题目链接:

    B-number

     HDU - 3652 

    题目大意:给你一个n,然后问你从1~n中有多少个数是能被13整除并且包含13的。

    具体思路:dp[i][j][k]表示到第i位的时候,余数为0,并且凑成13的类型为k的时候的状态(0为之前的没有凑齐过13,1为之前只凑齐了1,2位之前凑齐了13)(具体的j和k只是表示当前位数的余数是多少,并且类型为多少;具体算的时候还是算的当前位数之前的总合法的数目)

    数位DP求的就是一个前缀和?

    每一次dp[i][][] 表示的是当前位之后满足题目条件的个数,每一次dfs枚举的状态只是对于当前位和当前位之前的状态的一个表述。

    对于为什么要加一个限制条件,简单的举个例子,我们假设要找[1,210]这个区间满足的数,当百位取0的时候,我们十位当前枚举到了1这个状态,

    此时个位是能取0~9的,但是,当我们百位取2的时候,我们十位还是枚举到1这个状态,我们此时个位只能为0,但是如果不加限制条件的话,通过记搜,我们此时的个位状态还是按照0~9取的,也就是说会算多了,这也就是会算多的地方。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 # define inf 0x3f3f3f3f
     5 const int maxn = 1100;
     6 int a[maxn];
     7 int dp[maxn][14][3];
     8 int check(int t1,int t2){
     9 if(t1==1&&t2!=1&&t2!=3)return 0;
    10 if(t1==0&&t2==1)return 1;
    11 if(t1==1&&t2==3)return 2;
    12 return t1;
    13 }
    14 int dfs(int pos,int is_head,int mod,int is_13){
    15 if(!pos)return mod==0&&is_13==2;
    16 if(!is_head&&dp[pos][mod][is_13]!=-1)return dp[pos][mod][is_13];
    17 int fmax = is_head ? a[pos]:9;
    18 int ans=0;
    19 for(int i=0;i<=fmax;i++){
    20 ans+=dfs(pos-1,is_head&&i==fmax,(mod*10+i)%13,check(is_13,i));
    21 }
    22 if(!is_head)dp[pos][mod][is_13]=ans;
    23 return ans;
    24 }
    25 int cal(int t){
    26 int num=0;
    27 memset(dp,-1,sizeof(dp));
    28 while(t){
    29 a[++num]=t%10;
    30 t/=10;
    31 }
    32 return dfs(num,1,0,0);
    33 }
    34 int main(){
    35 int n;
    36 while(~scanf("%d",&n)){
    37 printf("%d
    ",cal(n));
    38 }
    39 return 0;
    40 }

     其实还可以把约束条件放在数组里面,也就是数组多开一维。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 const int maxn = 2e5  + 100;
     5 const int N  = 100;
     6 int dp[N][14][3][2];
     7 int a[N];
     8 int check(int t1,int t2){
     9 if(t1==1&&t2!=1&&t2!=3)return 0;
    10 if(t1==1&&t2==3)return 2;
    11 if(t1==1&&t2==1)return 1;
    12 if(t1==0&&t2==1)return 1;
    13 return t1;
    14 }
    15 int dfs(int pos,int is_head,int mod,int type){
    16 if(!pos)return mod==0&&type==2;
    17 if(dp[pos][mod][type][is_head]!=-1)return dp[pos][mod][type][is_head];
    18 int fmax = is_head ? a[pos] : 9;
    19 int ans=0;
    20 for(int i=0;i<=fmax;i++){
    21 ans+=dfs(pos-1,is_head&&i==fmax,(mod*10+i)%13,check(type,i));
    22 }
    23 dp[pos][mod][type][is_head]=ans;
    24 return ans;
    25 }
    26 int cal(int t){
    27 memset ( dp , -1 , sizeof(dp));
    28 int num=0;
    29 while(t){
    30 a[++num]=t%10;
    31 t/=10;
    32 }
    33 return dfs(num,1,0,0);
    34 }
    35 int main(){
    36 int n;
    37 while(~scanf("%d",&n)){
    38 printf("%d
    ",cal(n));
    39 }
    40 return 0;
    41 }
    View Code
  • 相关阅读:
    poj 3264 Balanced Lineup
    poj 2762 Going from u to v or from v to u?
    hdu 3671 Boonie and Clyde
    zoj 3195 Design the city
    poj 1523 SPF
    Codeforces Polo the Penguin and Matrix
    MVC原理的简述(转)
    C#访问权限修饰符
    XML Schema介绍
    Sql批量删除/插入
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10835109.html
Copyright © 2011-2022 走看看