数位DP-要49-基础DP-hdu3555-四种方法

来源:互联网 发布:淘宝选品数据分析 编辑:程序博客网 时间:2024/06/04 19:56

问1-n范围内存在49的个数。
大致找了四种方法
1 我用的反向查找的方法;
2 多状态记录的方法(好难写。不过挺有借鉴意义)
3 另一个网上找的大神的代码。
4 递推。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>long long dp[100][2];int cnt[100];using namespace std;long long  dfs(int len,bool status,bool limit){      if(len<0)  return 1;//计数       if(!limit&&dp[len][status]!=-1)           return dp[len][status];       int bow=0;       long long res=0;       bow=limit?cnt[len]:9;       for(int i=0;i<=bow;i++)       {   if(status&&i==9)              continue;           res+=dfs(len-1,i==4,i==bow&&limit);       }       if(!limit)//如果在limit上,是另行计算的。其实也就只是1而已。        dp[len][status]=res;        return res;}long long solve(long long  m){    memset(dp,-1,sizeof(dp));//计数也是可以成0的     memset(cnt,0,sizeof(cnt));     int len=0;     while(m)     {   cnt[len++]=m%10;         m/=10;     }     return dfs(len,false,true);    /*开头的设置也是特别有讲究*/}int main(){   long long m;int t;   cin>>t;    while(t--)      {   scanf("%lld",&m);           long long l=solve(m);           l--;           printf("%lld\n",m-l);      }    return 0;}
#include <iostream>#include <string.h>//dp[i][j]表示位数是i,状态为j//pos表示当前的位数//status中0表示不含49,1表示上一位是4,2表示含49//limit表示当前位是否受限制using namespace std;int digit[30];long long dp[30][3];int prepare(long long x){     memset(digit,0,sizeof(digit));    int cnt=0;    while(x)    {        digit[++cnt]=x%10;        x/=10;    }    return cnt;}long long solve(int pos,int status,int limit){    if(pos<=0)        return status==2;    if(!limit&&dp[pos][status]!=-1)        return dp[pos][status];//这里就是说比如257,那么当你计算过了0到99之后,100到199就可以直接调用了,而2这一位是有限制的,所以不能直接调用现成的,要到下面重新计算一下   long long ans=0;    int num=limit?digit[pos]:9;    for(int i=0;i<=num; i++)    {        int nstatus=status;//相当于else s=status;        if(status==0&&i==4)//高位不含49,并且末尾不是4,现在末尾添加的是4返回状态1            nstatus=1;        else if(status==1&&i!=4&&i!=9)//高位不含49,且末尾是4,现在末尾添加的不是4,返回状态0            nstatus=0;        else if(status==1&&i==9)//高位不含49,且末尾是4,现在末尾添加9,返回状态2            nstatus=2;            ans+=solve(pos-1,nstatus,limit&&i==num);    }    if(!limit)         dp[pos][status]=ans;    return ans;}int main(){    int T;    long long n;    ios::sync_with_stdio(false);    cin>>T;    while(T--)    {        memset(dp,-1,sizeof(dp));        cin>>n;        int len=prepare(n);       long long sum=solve(len,0,1);       cout<<sum<<endl;    }    return 0;}
#include <cstdio>  #include <cstring>  #include <iostream>  #include <cmath>  using namespace std;  #define RI(x) scanf("%d",&x)  #define PIN(x) printf("%d\n",x)  typedef long long ll;  const int N = 30;  ll z[N] = {1};  int t;  int bit[N];  ll dp[N][2], n;  ll dfs(int len, bool is4, bool ismax) {      if (len == 0)          return 0;      if (!ismax && dp[len][is4] >= 0)          return dp[len][is4];      ll cnt = 0;      int mmax = ismax ? bit[len] : 9;      for (int i = 0; i <= mmax; i++) {          if (is4 && i == 9) {              cnt += ismax ? n % z[len-1] + 1 : z[len-1];          } else {              cnt += dfs(len - 1, i == 4, ismax && bit[len] == i);          }      }      return ismax ? cnt : dp[len][is4] = cnt;  }  ll solve(ll n) {      int len = 0;      while (n) {          bit[++len] = n % 10;          n /= 10;      }      bit[len + 1] = 0;      return dfs(len, false, true);  }  int main() {      memset(dp, -1, sizeof(dp));      for (int i = 1; i < N; i++) {          z[i] = z[i - 1] * 10;      }      RI(t);      while (t--) {          scanf("%I64d", &n);          printf("I64d\n", solve(n));  //      cin >> n;  //      cout << solve(n) << endl;      }      return 0;  }  

递推

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;__int64 dp[25][3];void Init(){    memset(dp,0,sizeof(dp));    dp[0][0] = 1;    int i;    for(i = 1;i<=22;i++)    {        dp[i][0] = dp[i-1][0]*10-dp[i-1][1];        dp[i][1] = dp[i-1][0];        dp[i][2] = dp[i-1][2]*10+dp[i-1][1];    }}__int64 solve(__int64 n){    __int64 i,tem = n,len = 0,a[25],flag = 0,ans = 0;    while(n)    {        a[++len] = n%10;        n/=10;    }    a[len+1] = 0;    for(i = len;i;i--)    {        ans+=dp[i-1][2]*a[i];        if(flag)        ans+=dp[i-1][0]*a[i];        if(!flag && a[i]>4)        ans+=dp[i-1][1];        if(a[i+1] == 4 && a[i] == 9)        flag = 1;    }    return ans;}int main(){    int t;    __int64 n;    scanf("%d",&t);    Init();    while(t--)    {        scanf("%I64d",&n);        printf("%I64d\n",solve(n+1));    }    return 0;}
0 0
原创粉丝点击