zoukankan      html  css  js  c++  java
  • hdu 3652 "B-number"(数位DP)

    传送门

    参考博文:

      [1]:http://www.voidcn.com/article/p-drrnjrmy-wm.html

    题意:

      找出区间内数中含有13的并且能被13整除的数的个数

    题解:

      搜了好多博客,看到了一些关键词;

      其中一个就有"秦九韶算法",补了补秦九韶算法,再看一下参考博文的代码,感觉,和秦九韶算法关联不是太大;

      下面说说我的思路:

      假设 num = 121394 ,(num%13=0,且含有"13")

      num可写成 1*105+2*104+1*103+3*102+9*101+4;

      那么,将这个数任意拆分成两部分,例如 令 a = 1*105+2*104 , b=1*103+3*102+9*101+4;

      你会发现 a%13+b%13 = 13;

      (假设下标从0开始,最高为为 pos,从第 i 位置断开,[i+1,pos]组成的数为 a)

      那么,定义 dp[ i ][ j ][ k ]:

      dp[ i ][ j ][0]表示从pos到i+1位不含有"13"且 j = (13-a%13)的数的个数;

      dp[ i ][ j ][1]表示从pos到i+1位不含有"13"但是第i+1位是1且 j = (13-a%13)的数的个数 ;

      dp[ i ][ j ][2]表示从pos到i+1为含有"13"且 j =  (13-a%13) 的数的个数;

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 #define mem(a,b) memset(a,b,sizeof(a))
     6 
     7 int n;
     8 int digit[10];
     9 int dp[10][13][3];
    10 
    11 int quickPower(int a,int b)
    12 {
    13     int ans=1;
    14     while(b)
    15     {
    16         if(b&1)
    17             ans *= a;
    18         a *= a;
    19         b >>= 1;
    20     }
    21     return ans;
    22 }
    23 //s对应着0,1,2状态
    24 int DFS(int curPos,int curNum,int s,bool limit)
    25 {
    26     if(curPos == -1)
    27         return curNum%13 == 0 && s == 2 ? 1:0;
    28 
    29     //以 num = 121394 为例
    30     //如果当前的 curPos 来到 3数字处,那么 curNum = 121
    31     //而实际要算的是 13-121000%13,所以需要将curNum*1000,就是对应的quickPower()
    32     int mod=13-curNum*quickPower(10,curPos+1)%13;
    33     if(!limit&&dp[curPos][mod][s] != -1)
    34         return dp[curPos][mod][s];
    35 
    36     int up=limit ? digit[curPos]:9;
    37     int ans=0;
    38     for(int i=0;i <= up;++i)
    39     {
    40         int t=0;
    41         if(s == 2)
    42             t=2;
    43         else if(s == 1 && i == 3)
    44             t=2;
    45         else if(i == 1)
    46             t=1;
    47         ans += DFS(curPos-1,curNum*10+i,t,limit&&i==digit[curPos]);
    48     }
    49     if(!limit)
    50         dp[curPos][mod][s]=ans;
    51 
    52     return ans;
    53 }
    54 int Solve(int x)
    55 {
    56     int k=0;
    57     while(x)
    58     {
    59         digit[k++]=x%10;
    60         x /= 10;
    61     }
    62     return DFS(k-1,0,0,true);
    63 }
    64 int main()
    65 {
    66     mem(dp,-1);
    67     while(~scanf("%d",&n))
    68         printf("%d
    ",Solve(n));
    69 
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    Codeforces Round 269 (Div. 2)
    Codeforces Round 268 (Div. 2)
    杜教筛
    Codeforces Round 267(Div. 2)
    Codeforces Round 548 (Div. 2)
    Educational Codeforces Round 62 (Rated for Div. 2)
    数据结构编程实验——chapter9-应用二叉树的基本概念编程
    数据结构编程实验——chapter8-采用树结构的非线性表编程
    组合数学及其应用——polya计数
    《A First Course in Abstract Algebra with Applications》-chaper1-数论-棣莫弗定理
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10619430.html
Copyright © 2011-2022 走看看