hdu 3555 Bomb

来源:互联网 发布:windows多线程互斥 编辑:程序博客网 时间:2024/05/16 05:52
//第一个数位dp,由于别人的看不懂,然后自己还是摸索出来了,虽然写得比较麻烦,思路还是清楚的,dfs枚举每种情况就好了,要记忆化搜索,不然会超时,这题得用__int64#include<iostream>#include<cstdio>#include<cstring>using namespace std;int num[22];__int64 dp[22][10][2];int l;__int64 dfs(int i,int j,bool find,bool flag){          if(i==l&&find)return 1;          if(i==l||j<0)return 0;          if(!flag&&dp[i][j][find]!=-1)return dp[i][j][find];         if(find)         {                if(!flag)return  dp[i][j][find]=10*dfs(i+1,0,1,0);                return num[i]*dfs(i+1,0,1,0)+dfs(i+1,0,1,1);         }         if(!flag)         {            if(j==4)return  dp[i][j][find]=dfs(i+1,9,1,0)+dfs(i+1,4,0,0)+8*dfs(i+1,0,0,0);            return  dp[i][j][find]=dfs(i+1,4,0,0)+9*dfs(i+1,0,0,0);         }        if(j==4&&num[i]==9)return dfs(i+1,9,1,1)+dfs(i+1,4,0,0)+8*dfs(i+1,0,0,0);        if(num[i]==4)return dfs(i+1,4,0,1)+4*dfs(i+1,0,0,0);        if(num[i]>4) return  dfs(i+1,4,0,0)+dfs(i+1,0,0,1)+(num[i]-1)*dfs(i+1,0,0,0);        return dfs(i+1,0,0,1)+num[i]*dfs(i+1,0,0,0);}int main(){   __int64 n;int t;scanf("%d",&t);   while(t--)   {         scanf("%I64d",&n);         int k=0;         while(n)         {              num[k++]=n%10;              n/=10;         }         l=k;         memset(dp,-1,sizeof(dp));         for(int i=0;i<l/2;i++)swap(num[i],num[l-1-i]);         printf("%I64d\n",dfs(0,0,0,1));   }   return 0;}


0 0