几个基础数位DP (hdu 2089,hdu 3555 ,uestc 1307 windy 数)

来源:互联网 发布:h5游戏源码搭建 编辑:程序博客网 时间:2024/06/08 09:15
 HDU 2089 不要62
http://acm.hdu.edu.cn/showproblem.php?pid=2089
不能出现4,或者相邻的62,这题可以暴力打表解决

具体的在代码里都有解释

#include<iostream>  #include<cstring>  #include<queue>  #include<cstdio>  #include<cmath>  #include<algorithm>  #define N 55  #define inf 1<<29  #define MOD 9973  #define LL long long  #define eps 1e-7  #define zero(a) fabs(a)<eps  #define equal(a,b) zero(a-b)  using namespace std;  int dp[10][3];  //dp[i][0],表示不存在不吉利数字  //dp[i][1],表示不存在不吉利数字,且最高位为2  //dp[i][2],表示存在不吉利数字  void Init(){      memset(dp,0,sizeof(dp));      dp[0][0]=1;      for(int i=1;i<=6;i++){          dp[i][0]=dp[i-1][0]*9-dp[i-1][1];  //在最高位加上除了4之外的9个数字,但是可能在2之前加了6          dp[i][1]=dp[i-1][0];    //就是在原先不含不吉利数字的最高位加2          dp[i][2]=dp[i-1][2]*10+dp[i-1][0]+dp[i-1][1];  //在已经有不吉利数字最高位加任意数字,或者在无吉利数字前加4,或者在2前面加4      }  }  int slove(int n){      int len=0,bit[10];      int tmp=n;      while(n){          bit[++len]=n%10;          n/=10;      }      bit[len+1]=0;      int ans=0;      bool flag=false;      for(int i=len;i;i--){          ans+=dp[i-1][2]*bit[i];            if(flag)   //高位已经出现4或者62,后面的就随意              ans+=dp[i-1][0]*bit[i];          if(!flag&&bit[i]>4)  //高位可能出现4的情况              ans+=dp[i-1][0];          if(!flag&&bit[i+1]==6&&bit[i]>2)  //高位是6,后面一位可能出现2,这步debug了很久              ans+=dp[i][1];          if(!flag&&bit[i]>6)  //高位可能出现6,要把后面最高位为2计入              ans+=dp[i-1][1];          if(bit[i]==4||(bit[i+1]==6&&bit[i]==2))  //高位已经出现4或者62              flag=true;      }      return tmp-ans;  }  int main(){      int l,r;      Init();      while(scanf("%d%d",&l,&r)!=EOF&&l+r)          printf("%d\n",slove(r+1)-slove(l));      return 0;  }  



HDU 3555 BOMB

http://acm.hdu.edu.cn/showproblem.php?pid=3555
不能出现相邻的49,和上一题类似


#include<iostream>  #include<cstring>  #include<queue>  #include<cstdio>  #include<cmath>  #include<algorithm>  #define N 55  #define inf 1<<29  #define MOD 9973  #define LL long long  #define eps 1e-7  #define zero(a) fabs(a)<eps  #define equal(a,b) zero(a-b)  using namespace std;  LL dp[21][3],n;   int len,bit[21];  //dp[i][0]表示长度为i,包括49的个数  //dp[i][1]表示长度为i,没有49但是开头为9的个数  //dp[i][2]表示长度为i,没有49  void Init(){      memset(dp,0,sizeof(dp));      dp[0][2]=1;      for(int i=1;i<20;i++){          dp[i][0]=(LL)dp[i-1][0]*10+dp[i-1][1];          dp[i][1]=dp[i-1][2];          dp[i][2]=(LL)dp[i-1][2]*10-dp[i-1][1];      }  }  int main(){      Init();      int t;      scanf("%d",&t);      while(t--){          scanf("%I64d",&n);          len=0;          n++;          while(n){              bit[++len]=n%10;              n/=10;          }          bit[len+1]=0;          LL ans=0;          bool flag=false;          for(int i=len;i;i--){              ans+=(LL)dp[i-1][0]*bit[i];              if(flag)                  ans+=(LL)dp[i-1][2]*bit[i];              if(!flag&&bit[i]>4)                  ans+=dp[i-1][1];              if(bit[i]==9&&bit[i+1]==4)                  flag=true;          }          printf("%I64d\n",ans);      }      return 0;  }  

#include<iostream>  #include<cstring>  #include<queue>  #include<cstdio>  #include<cmath>  #include<algorithm>  #define N 100005  #define inf 1<<29  #define MOD 9973  #define LL long long  #define eps 1e-7  #define zero(a) fabs(a)<eps  #define equal(a,b) zero(a-b)  using namespace std;  int dp[15][10];  //dp[i][j]表示考虑i位的数中,最高为j的windy数  void Init(){      memset(dp,0,sizeof(dp));      for(int i=0;i<=9;i++)          dp[1][i]=1;      for(int i=2;i<=10;i++){          for(int j=0;j<10;j++){              for(int k=0;k<10;k++)                  if(abs(j-k)>=2)                      dp[i][j]+=dp[i-1][k];          }      }  }  int slove(int n){      int len=0,bit[15];      while(n){          bit[++len]=n%10;          n/=10;      }      bit[len+1]=0;      int ans=0;      //先把长度为1至len-1计入      for(int i=1;i<len;i++)          for(int j=1;j<10;j++)              ans+=dp[i][j];      //确定最高位      for(int j=1;j<bit[len];j++)          ans+=dp[len][j];      for(int i=len-1;i;i--){          for(int j=0;j<bit[i];j++)              if(abs(j-bit[i+1])>=2)                  ans+=dp[i][j];          //如果高位已经出现非法,直接退出          if(abs(bit[i]-bit[i+1])<2)              break;      }      return ans;  }  int main(){      Init();      int l,r;      while(scanf("%d%d",&l,&r)!=EOF)          printf("%d\n",slove(r+1)-slove(l));      return 0;  }  





UESTC 1307 WINDY 数
http://acm.uestc.edu.cn/problem.php?pid=1307
要求相邻的数差大于等于2



0 0
原创粉丝点击