zoukankan      html  css  js  c++  java
  • uva 10712

    题目链接:uva 10712 - Count the Numbers


    题目大意:给出n,a。b。问说在a到b之间有多少个n。


    解题思路:数位dp。dp[i][j][x][y]表示第i位为j的时候。x是否前面是相等的。y是否已经出现过n。对于n=0的情况要特殊处理前导0,写的很乱。搓死。


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N = 20;
    const int M = 1005;
    
    ll A, B, n, a[N], dp[N][M][2][2];
    
    void del (ll u, ll* p) {
    	ll& c = p[0];
    	c = 0;
    
    	while (u) {
    		p[++c] = u % 10;
    		u /= 10;
    	}
    
    	if (c == 0)
    		p[++c] = 0;
    
    	for (int i = 1; i <= c / 2; i++)
    		swap(p[i], p[c-i+1]);
    }
    
    ll cat (ll u) {
    
    	if (u == 0)
    		return 1;
    
    	int s = 0;
    	ll f[N][N][2];
    	memset(f, 0, sizeof(f));
    
    	for (int i = 1; i <= a[0]; i++) {
    		
    		for (int j = 0; j < 10; j++) {
    			for (int k = 0; k < 10; k++) {
    				f[i][j][1] += f[i-1][k][1];
    				if (j)
    					f[i][j][0] += f[i-1][k][0];
    				else
    					f[i][j][1] += f[i-1][k][0];
    			}
    		}
    
    		if (a[i] == 0)
    			s = 1;
    		else if (i > 1)
    			f[i][0][1]++;
    
    		for (int j = 1; j < a[i]; j++)
    			f[i][j][s]++;
    		if (i > 1) {
    			for (int j = 1; j < 10; j++)
    				f[i][j][0]++;
    		}
    	}
    
    	ll ans = 0;
    	if (s)
    		ans++;
    
    	for (int i = 0; i < 10; i++)
    		ans += f[a[0]][i][1];
    	return ans + 1;
    }
    
    ll solve (ll u) {
    	if (u < n)
    		return 0;
    
    	del(u, a);
    
    	if (n == 0)
    		return cat(u);
    
    	memset(dp, 0, sizeof(dp));
    
    	dp[0][0][1][0] = 1;
    
    	ll v = n, tmp = 1;
    
    	if (v) {
    		while (v) {
    			v /= 10;
    			tmp *= 10;
    		}
    	} else {
    		tmp = 10;
    	}
    	ll mod = tmp / 10;
    
    	for (int i = 1; i <= a[0]; i++) {
    
    		for (int j = 0; j < tmp; j++) {
    
    			for (int k = 0; k < 10; k++) {
    				int x = (j % mod) * 10 + k;
    
    				if (x == n) {
    					dp[i][x][0][1] += (dp[i-1][j][0][0] + dp[i-1][j][0][1]);
    					if (k < a[i])
    						dp[i][x][0][1] += (dp[i-1][j][1][0] + dp[i-1][j][1][1]);
    					else if (k == a[i])
    						dp[i][x][1][1] += (dp[i-1][j][1][0] + dp[i-1][j][1][1]);
    				} else {
    					dp[i][x][0][0] += dp[i-1][j][0][0];
    					dp[i][x][0][1] += dp[i-1][j][0][1];
    
    					if (k < a[i]) {
    						dp[i][x][0][0] += dp[i-1][j][1][0];
    						dp[i][x][0][1] += dp[i-1][j][1][1];
    					} else if (k == a[i]) {
    						dp[i][x][1][0] += dp[i-1][j][1][0];
    						dp[i][x][1][1] += dp[i-1][j][1][1];
    					}
    				}
    			}
    		}
    	}
    
    	int c = a[0];
    	ll ans = 0;
    	for (int i = 0; i < tmp; i++)
    		ans += (dp[c][i][0][1] + dp[c][i][1][1]);
    	return ans;
    }
    
    int main () {
    	while (scanf("%lld%lld%lld", &A, &B, &n) == 3) {
    		if (A == -1 || B == -1 || n == -1)
    			break;
    		printf("%lld
    ", solve(B) - solve(A-1));
    	}
    	return 0;
    }
    


  • 相关阅读:
    抽象工厂与工厂方法的区别
    工作那些年的事兒
    抽象工廠與工廠方法的區別
    Dot Net设计模式—MVC模式
    Log4Net配置
    FileStream的使用
    asp.net用户检测的两种方式
    SWFUpload无刷新文件批量上传
    页面生命周期
    Lambda表达式与匿名方法
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8919121.html
Copyright © 2011-2022 走看看