• hdu 3709+hdu 3555(数位dp)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709

    数位dp...完全看大牛模版理解的。。。。

    View Code
     1 #include<iostream>
     2 using namespace std;
     3 __int64 dp[19][19][2000];
     4 int digit[19];
     5 
     6 //pos表示当前的位置,o表示支点,pre表示从最高位到pos的力矩之和,doing表示是否有上限,若无,则为9;
     7 __int64 dfs(int pos,int o,int pre,bool doing){
     8     if(pos==-1){
     9         return pre==0;  //已经全部组合
    10     }
    11     if(pre<0)return 0;//如果前面组合的力矩之和已经为负,则后面的必然小于0;
    12     //没有上限,且前面的状态已经搜过
    13     if(!doing&&dp[pos][o][pre]!=-1){
    14         return dp[pos][o][pre];
    15     }
    16     __int64 ans=0;
    17     int end=doing?digit[pos]:9;
    18     for(int i=0;i<=end;i++){
    19         int npre=pre;   //枚举下一个状态
    20         npre+=(pos-o)*i;   
    21         ans+=dfs(pos-1,o,npre,doing&&i==end);
    22     }
    23     if(!doing){
    24         dp[pos][o][pre]=ans;
    25     }
    26     return ans;
    27 }
    28 
    29 __int64 solve(__int64 n){
    30     int pos=0;
    31     while(n){
    32         digit[pos++]=n%10;
    33         n/=10;
    34     }
    35     __int64 ans=0;
    36     for(int o=0;o<pos;o++){
    37         ans+=dfs(pos-1,o,0,1);
    38     }
    39     return ans-(pos-1);//0,00,000....这种情况
    40 }
    41 
    42 int main(){
    43     int _case;
    44     scanf("%d",&_case);
    45     memset(dp,-1,sizeof(dp));
    46     while(_case--){
    47         __int64 n,m;
    48         scanf("%I64d%I64d",&n,&m);
    49         printf("%I64d\n",solve(m)-solve(n-1));
    50     }
    51     return 0;
    52 }

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555

    View Code
     1 #include<iostream>
     2 using namespace std;
     3 __int64 dp[20][3];
     4 int digit[20];
     5 
     6 //have==1表示前一位为4,have==0表示没有出现49,have==2表示前面有49出现
     7 __int64 dfs(int pos,int have,bool doing){
     8     if(pos==-1){
     9         return have==2;//找到一个解
    10     }
    11     if(!doing&&dp[pos][have]!=-1){
    12         return dp[pos][have];
    13     }
    14     __int64 ans=0;
    15     int end=doing?digit[pos]:9;
    16     for(int i=0;i<=end;i++){
    17         int nhave=have;
    18         if(have==1&&i!=4){
    19             nhave=0;
    20         }
    21         if(have==0&&i==4){
    22             nhave=1;
    23         }
    24         if(have==1&&i==9){
    25             nhave=2;
    26         }
    27         ans+=dfs(pos-1,nhave,doing&&i==end);
    28     }
    29     if(!doing)
    30         dp[pos][have]=ans;
    31     return ans;
    32 }
    33 
    34 __int64 solve(__int64 n){
    35     int pos=0;
    36     while(n){
    37         digit[pos++]=n%10;
    38         n/=10;
    39     }
    40     return dfs(pos-1,0,1);
    41 }
    42 
    43 int main(){
    44     int _case;
    45     scanf("%d",&_case);
    46     memset(dp,-1,sizeof(dp));
    47     while(_case--){
    48         __int64 n;
    49         scanf("%I64d",&n);
    50         printf("%I64d\n",solve(n));
    51     }
    52     return 0;
    53 }

    昨天做的fzu的月赛。。。当时没过。。。

    http://acm.fzu.edu.cn/contest/problem.php?cid=126&sortid=1

    这个代码我没提交过。。。

    View Code
     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 __int64 dp[20][20];
     5 int digit[20];
     6 
     7 __int64 DFS(int pos,int have,bool doing){
     8     if(pos==-1){
     9         return have;
    10     }
    11     if(!doing&&dp[pos][have]!=-1){
    12         return dp[pos][have];
    13     }
    14     __int64 ans=0;
    15     int end=doing?digit[pos]:9;
    16     for(int i=0;i<=end;i++){
    17         int nhave=have;
    18         if(i==1)nhave=have+1;
    19         ans+=DFS(pos-1,nhave,doing&&i==end);
    20     }
    21     if(!doing){
    22         dp[pos][have]=ans;
    23     }
    24     return ans;
    25 }
    26 
    27 
    28 __int64 solve(__int64 n){
    29     int pos=0;
    30     while(n){
    31         digit[pos++]=n%10;
    32         n/=10;
    33     }
    34     return DFS(pos-1,0,1);
    35 }
    36 
    37 int main(){ 
    38     __int64 n,m;
    39     memset(dp,-1,sizeof(dp));
    40     while(~scanf("%I64d%I64d",&n,&m)){
    41         printf("%I64d\n",solve(m)-solve(n-1));
    42     }
    43     return 0;
    44 }
    45 
    46         

    PS:记忆化搜索真的很强大啊。。。

  • 相关阅读:
    ActiveMQ的作用总结(应用场景及优势)
    深入剖析ThreadLocal实现原理以及内存泄漏问题
    Java ThreadLocal 原理分析
    关于iview ui的"Page分页"组件的使用
    使用TortoiseGit操作分支的创建与合并
    乐观锁与悲观锁的区别
    Linux下如何安装MongoDB及配置
    centos8安装图解(超详细教程)
    SpringBoot整合MongoDB
    PPT学习---醍醐灌顶!你对PPT的理解过时了!
  • 原文地址:https://www.cnblogs.com/wally/p/3006115.html
Copyright © 2020-2023  润新知