HDU-3886-数位dp

来源:互联网 发布:网络贷款 预防诈骗 编辑:程序博客网 时间:2024/05/18 02:39

题目大意:为一个区间内有多少数满足给定函数曲线的数的个数;

题目解析:首先因为数据很大,需要用字符串保存,并且要处理掉前导零,否则会对答案有影响,dp第二维表示前一个数是多少,dp的第三维表示当前表示的opt;

AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>using namespace std;typedef long long ll;const int mod=100000000;int dp[150][12][150],len;string op,s;void add(int &a,int b){a+=b;a=a%mod;}bool judge(int pre,int now,int cnt){if(op[cnt]=='/')return pre<now;else if(op[cnt]=='\\')return pre>now;else if(op[cnt]=='-')return pre==now;return 0;}int dfs(int pos,int pre,int tar,bool lead,bool limit){if(pos==-1)return tar==len;if(!lead&&!limit&&dp[pos][pre][tar]!=-1)return dp[pos][pre][tar];int u=limit?s[pos]-'0':9;int ans=0;for(int i=0;i<=u;i++){if(lead){if(i==0)add(ans,dfs(pos-1,-1,tar,true,limit&&i==u));else add(ans,dfs(pos-1,i,tar,false,limit&&i==u));}else {if(judge(pre,i,tar)&&tar<len)add(ans,dfs(pos-1,i,tar+1,false,limit&&i==u));else if(judge(pre,i,tar-1)&&tar>0)add(ans,dfs(pos-1,i,tar,false,limit&&i==u));}}if(!limit&&!lead)return dp[pos][pre][tar]=ans;return ans;}int solve(string l) {      s = l;      return dfs(s.size()-1, -1, 0, 1, 1);  }  void cut(string &s, bool g) {      int i = 0;      while(i < s.size() && s[i] == '0') i++;      if(i == s.size()) s = "0";      else s = s.substr(i, s.size()-i);      reverse(s.begin(), s.end());      if(g && s != "0") {          s[0]--;          for(i = 0; i < s.size()-1; i++)              if(s[i] < '0') {                  s[i] += 10;                  s[i+1]--;              }          if(s[0] < '0') s[0] = '0';      }      i = s.size()-1;      while(i >= 0 && s[i] == '0') i--;      if(i == -1) s = "0";      else s = s.substr(0, i+1); //cout<<s<<endl;  }  int main(){string l,r;while(cin>>op>>l>>r){len=op.size();memset(dp,-1,sizeof(dp));cut(l,1);cut(r,0);printf("%08d\n",(solve(r)-solve(l)+mod)%mod);}return 0;}



0 0
原创粉丝点击