BNUOJ 52325 Increasing or Decreasing 数位dp

题目链接:

https://acm.bnu.edu.cn/v3/contest_show.php?cid=8506#problem/I

I. Increasing or Decreasing


Case Time Limit: 1000msMemory Limit: 524288KB

题意

求[l,r]上,数位满足非递增获非递减的数的个数。

题解

1、dp[i][j][k]表示低i位的第i位为j的,k==1时表示满足非递减,k==2时满足非递增,k==0时表示每一位都相等。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "< VI;
typedef pair PII;
typedef vector > VPII;const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);//start----------------------------------------------------------------------const int maxn=22;int arr[maxn],tot;
///type根据dp具体维数调整
LL dp[maxn][11][4];
///ismax标记表示前驱是否是边界值
///ser标记前驱是否是前导零
LL dfs(int len,int dig,int type,bool ismax,bool iszer) {if (len == 0) {///递归边界,这说明前驱都合法了return 1LL;}if (!ismax&&dp[len][dig][type]>=0) return dp[len][dig][type];LL res = 0;int ed = ismax ? arr[len] : 9;///这里插入递推公式for (int i = 0; i <= ed; i++) {if(i==0&&iszer){///处理前导零res+=dfs(len-1,10,0,ismax&&i==ed,1);}else{if(type==0){if(i==dig||dig==10) res+=dfs(len-1,i,0,ismax&&i==ed,0);else if(i>dig) res+=dfs(len-1,i,1,ismax&&i==ed,0);else if(i=dig){res+=dfs(len-1,i,type,ismax&&i==ed,0);}}else if(type==2){if(i<=dig){res+=dfs(len-1,i,type,ismax&&i==ed,0);}}}}return ismax ? res : dp[len][dig][type] = res;
}LL solve(LL x) {tot = 0;while (x) { arr[++tot] = x % 10; x /= 10; }LL ret=0;return dfs(tot,10,0,true,true);
}void init() {clr(dp,-1);
}int main() {init();int n; scf("%d",&n);while(n--){LL l,r;scf("%lld%lld",&l,&r);prf("%lld\n",solve(r)-solve(l-1));}return 0;
}//end-----------------------------------------------------------------------

2、状态和上面差不多,不过是固定k,分别求出来,既ans=非递增+非递减-每个数位都相同。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "< VI;
typedef pair PII;
typedef vector > VPII;const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);//start----------------------------------------------------------------------const int maxn=22;int arr[maxn],tot;
///type根据dp具体维数调整
LL dp[maxn][11][4];
///ismax标记表示前驱是否是边界值
///ser标记前驱是否是前导零
LL dfs(int len,int dig,int type,bool ismax,bool iszer) {if (len == 0) {///递归边界,这说明前驱都合法了return 1LL;}if (!ismax&&dp[len][dig][type]>=0) return dp[len][dig][type];LL res = 0;int ed = ismax ? arr[len] : 9;///这里插入递推公式for (int i = 0; i <= ed; i++) {if(i==0&&iszer){///处理前导零res+=dfs(len-1,10,type,ismax&&i==ed,true);}else{if(type==1){if(i>=dig||dig==10) res+=dfs(len-1,i,type,ismax&&i==ed,false);}else if(type==2){if(i<=dig||dig==10) res+=dfs(len-1,i,type,ismax&&i==ed,false);}else if(type==0){if(i==dig||dig==10) res+=dfs(len-1,i,type,ismax&&i==ed,false);}}}return ismax ? res : dp[len][dig][type] = res;
}LL solve(LL x) {tot = 0;while (x) { arr[++tot] = x % 10; x /= 10; }LL ret=0;ret+=dfs(tot,10,1,true,true);ret+=dfs(tot,10,2,true,true);ret-=dfs(tot,10,0,true,true);return ret;
}void init() {clr(dp,-1);
}int main() {init();int n; scf("%d",&n);while(n--){LL l,r;scf("%lld%lld",&l,&r);prf("%lld\n",solve(r)-solve(l-1));}return 0;
}//end-----------------------------------------------------------------------

转载于:https://www.cnblogs.com/fenice/p/5935215.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部