zoukankan      html  css  js  c++  java
  • UVa 12212 Password Remembering (数位dp)

    题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=244&page=show_problem&problem=3364

    (dp[i][j][0/1][0/1][0/1/2][0/1/2]) 表示当前是原数的第 (i) 位,翻转后是翻转数的第 (j) 位(因为有前导零,所以位置可能不变),原数卡不卡下界,原数卡不卡上界,前 (i) 位的原数翻转后小于/等于/大于后 (j) 位的上/下界

    转移分类讨论即可,其中翻转后数字的大小关系,是从低位向高位维护的

    注意原数前导零和最后连续的零翻转后的变化,小心处理即可,还要使用 (unsigned long long)

    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef unsigned long long ull;
    
    const int maxn = 70;
    
    int T;
    ull A, B;
    ull dp[maxn][maxn][2][2][3][3];
    int a[maxn], b[maxn];
    int ca, cb;
    
    ull dfs(int pos, int rpos, int llx, int lls, int lrx, int lrs, int lead){ // llx 原数下界, lls 原数上界, lrx 翻转数下界, lrs 翻转数上界 
    	if(pos == 0) {
    		int fx = 0, fs = 0;
    		if(rpos-1 >= ca && lrx >= 1) fx = 1;
    		if(rpos-1 < cb || (rpos-1 == cb && lrs <= 1)) fs = 1;
    		if(fx && fs) return 1;
    		else return 0; 
    	}
    	if(!lead && dp[pos][rpos][llx][lls][lrx][lrs] != -1) return dp[pos][rpos][llx][lls][lrx][lrs];
    	
    	int lmx = llx ? a[pos] : 0;
    	int lms = lls ? b[pos] : 9;
    	
    	ull res = 0;
    	for(int i = lmx ; i <= lms ; ++i){ // 枚举原数第 i 个位置 
    		int ns, nx;
    		if(i > b[rpos]){ // 新的位置的数大于翻转数上界 
    			ns = 2; 
    		} else if(i == b[rpos]){ // 等于 
    			ns = lrs;
    		} else{ // 小于 
    			ns = 0;
    		}
    			
    		if(i < a[rpos]){ // 新的位置小于翻转数下界 
    			nx = 0;
    		} else if(i == a[rpos]){
    			nx = lrx;
    		} else{
    			nx = 2;
    		}
    		
    		if(lead && i == 0) { // 前导 0, 并且满足下界条件 
    			res += dfs(pos-1, rpos, 1, 0, 1, 1, 1);
    		}
    		else res += dfs(pos-1, rpos+1, llx && (i == lmx), lls && (i == lms), nx, ns, 0);
    	}
    	
    	if(!lead) dp[pos][rpos][llx][lls][lrx][lrs] = res;
    	return res;
    }
    
    ull solve(){
    	memset(a, 0, sizeof(a));
    	memset(b, 0, sizeof(b));
    	memset(dp, -1, sizeof(dp));
    	ull tmp = A;
    	ca = 0, cb = 0;
    	while(tmp){
    		a[++ca] = tmp % 10;
    		tmp /= 10;
    	}
    	
    	tmp = B;
    	while(tmp){
    		b[++cb] = tmp % 10;
    		tmp /= 10;
    	}
    	
    	return dfs(cb, 1, 1, 1, 1, 1, 1);
    }
    
    int main(){
    	int T;
    	scanf("%d", &T); 
    	for(int kase = 1 ; kase <= T ; ++kase){
    		scanf("%llu%llu", &A, &B);
    		printf("Case %d: %llu
    ", kase, solve());
    	}
    	return 0;
    }
    
  • 相关阅读:
    深入分析 Python 的垃圾回收机制
    9.26
    Web安全之ML--构建机器学习工具箱
    第八节--图的数据结构及其算法
    第七节--树形结构及其算法
    第六节--堆栈与队列算法
    第四节--查找与哈希算法
    第三节--排序算法
    第二节--常用数据结构
    第一节--走入算法的世界
  • 原文地址:https://www.cnblogs.com/tuchen/p/15142399.html
Copyright © 2011-2022 走看看