HDU 3555 水数位dp

来源:互联网 发布:cnnic数据报告 2017 编辑:程序博客网 时间:2024/04/29 07:46

和 hdu 2089 一样的思路,这个是找数字中带有 49 的,我dp的不带 49 的 一减就可以了。

dp 出来的个数是从0 开始的。

当然。。。后来。。。就是现在。。我又写了另一个版本。。。找数字中带有 49 的。代码在下面。。

#include <stdio.h>#include <iostream>#include <queue>#include <algorithm>#include <map>#include <vector>#include <cmath>#include <string.h>#include <stdlib.h>#include <time.h>#include <fstream>#include <set>#include <stack>using namespace std;#define READ freopen("acm.in","r",stdin)#define WRITE freopen("acm.out","w",stdout)#define ll long long#define ull unsigned long long #define PII pair<int,int>#define PDI pair<double,int>#define PDD pair<double,double>#define MII map<int,int>::iterator #define fst first#define sec second#define MS(x,d) memset(x,d,sizeof(x))#define INF 0x3f3f3f3f#define ALL(x) x.begin(),x.end()#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define ROOT 0,n-1,1#define PB push_back#define FOR(a,b,c) for(int a=b;a<c;a++)#define MOD 10007#define keyTree (ch[ ch[root][1] ][0])#define MAX 111ll dp[MAX][MAX];int digit[MAX];int len;ll dfs(int i,int s,bool e){    if(i==0)        return s==0;    if(!e&&dp[i][s]!=-1)        return dp[i][s];    int u=e?digit[i-1]:9;    ll res=0;    for(int j=0;j<=u;j++)    {        if(!(s==4&&j==9))            res+=dfs(i-1,j,e&&j==u);    }    return e?res:dp[i][s]=res;}ll cal(ll n){    MS(digit,0);    len=0;    while(n)    {        digit[++len]=n%10;        n/=10;    }    return dfs(len+1,0,1);}int main(){    MS(dp,-1);    int cas;    scanf("%d",&cas);    while(cas--)    {        ll t;        cin>>t;        cout<<t+1-cal(t)<<endl;    }    return 0;}

其实写完不要62就觉得挺奇怪的。。为毛我觉得写不要62和要62感觉差距好多。。

后来想了。。。很久。。原来是状态不够细啊。。。

dp[i][j][flag] 表示长度为 i 的开头为 j 的数字中 带49的有几个。。不带49 的有几个,这样状态描述才完整

否则的话。。转移的时候很难搞。。。到底该咋转移才能不重复呢。。比如说。。s=4,j=9 的时候,如果直接加的话。。会有漏算的,因为后面不带49的现在也带49了,不直接加的话。。又会少。。所以,dp 中状态描述完整是最重要和最前面的一步。

#include <stdio.h>#include <iostream>#include <queue>#include <algorithm>#include <map>#include <vector>#include <cmath>#include <string.h>#include <stdlib.h>#include <time.h>#include <fstream>#include <set>#include <stack>using namespace std;#define READ freopen("acm.in","r",stdin)#define WRITE freopen("acm.out","w",stdout)#define ll long long#define ull unsigned long long #define PII pair<int,int>#define PDI pair<double,int>#define PDD pair<double,double>#define MII map<int,int>::iterator #define fst first#define sec second#define MS(x,d) memset(x,d,sizeof(x))#define INF 0x3f3f3f3f#define ALL(x) x.begin(),x.end()#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define ROOT 0,n-1,1#define PB push_back#define FOR(a,b,c) for(int a=b;a<c;a++)#define MOD 10007#define keyTree (ch[ ch[root][1] ][0])#define MAX 111ll dp[MAX][MAX][3];int digit[MAX];int len;ll fac[100];ll dfs(int i,int s,int flag,bool e){    if(i==1&&flag)        return 0;    if(i==1&&!flag)        return 1;    if(!e&&dp[i][s][flag]!=-1)        return dp[i][s][flag];    int u=e?digit[i-1]:9;    ll res=0;    for(int j=0;j<=u;j++)    {        if(!flag&&s==4&&j==9)            continue;        res+=dfs(i-1,j,flag,e&&j==u);        if(flag&&s==4&&j==9)            res+=dfs(i-1,j,0,e&&j==u);    }    return e?res:dp[i][s][flag]=res;}ll cal(ll n){    MS(digit,0);    len=0;    while(n)    {        digit[++len]=n%10;        n/=10;    }    return dfs(len+1,0,1,1);}int main(){    MS(dp,-1);    int cas;    scanf("%d",&cas);    fac[0]=1;    for(int i=1;i<20;i++)        fac[i]=10*fac[i-1];    while(cas--)    {        ll t;        cin>>t;        cout<<cal(t)<<endl;    }    return 0;}


0 0
原创粉丝点击