• HDU 3555 Bomb 数位dp


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=3555

    Bomb

    Time Limit: 2000/1000 MS (Java/Others)
    Memory Limit: 131072/65536 K (Java/Others)
    #### 问题描述 > The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would add one point. > Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them? #### 输入 > The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description. > > The input terminates by end of file marker. #### 输出 > For each test case, output an integer indicating the final points of the power. #### 样例 > **sample input** > 3 > 1 > 50 > 500 > > **sample output** > 0 > 1 > 15

    题意

    给你一个数n,求1到n里面有多少个数其中存在子串49的。

    题解

    数位dp。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    
    const int maxn = 20;
    typedef long long LL;
    
    //dp[len][0]表示长度<=len,且不包含49的总数
    //dp[len][1]表示长度<=len,且以9结尾但不包含49的总数
    //dp[len][2]表示长度<=len,且包好49的总数
    //dp[len][0]+dp[len][2]=所有长度小于等于len的数。
    //dp[len][1]是dp[len][0]的一个子集。
    LL dp[maxn][3];
    void pre() {
    	memset(dp, 0, sizeof(dp));
    	dp[0][0] = 1;
    	for (int i = 1; i < maxn; i++) {
    		dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1];
    		dp[i][1] = dp[i - 1][0];
    		dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1];
    	}
    }
    
    int main() {
    	pre();
    	int tc;
    	scanf("%d", &tc);
    	while (tc--) {
    		LL x; scanf("%I64d", &x);
    		LL ans = 0;
    		int arr[maxn], tot=0;
    		while (x) { arr[++tot]=x%10; x /= 10; }
    		bool flag = false; //标记x的高位时否已经出现49的组合。
    		for (int i = tot; i >= 1; i--) {
    			//这时考虑的是高位已经固定,这一位数为0(是可以有0的,因为高位还会有数,虽然最高位后面每数了,但它统计的是<=len,
    			//而不是==len!!!)到arr[i]-1的所有情况中包好49的数
    			ans += dp[i-1][2] * arr[i];
    			if (flag) ans += dp[i-1][0] * arr[i];
    			else if (arr[i] > 4) {//如果4刚好是arr[i],那也是不能乱搞的!边界情况我们会一直往后推来考虑
    				ans += dp[i - 1][1];
    			}
    			if (i + 1 <= tot&&arr[i] == 9 && arr[i + 1] == 4) {
    				flag = 1;
    			}
    		}
    		if (flag) ans++;
    		printf("%I64d
    ", ans);
    	}
    	return 0;
    }
    

    再来一发dfs:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    
    const int maxn = 20;
    typedef __int64 LL;
    
    //dp[len][0]是给第len+1位不为4的时候用的
    //dp[len][1]是给第len+1位为4的时候用的(有点像私人订制)
    //我们只保存没有限制的状态,对于有限制的状态每次都要算,不过没有限制的状态出现的要不有限制的多的多。
    LL dp[maxn][2],ten[maxn];
    LL n;
    
    int arr[maxn];
    LL dfs(int len, int is4, int ismax) {
    	if (len == 0) return 0;
    	if (!ismax&&dp[len][is4] >= 0) return dp[len][is4];
    	LL res = 0;
    	int ed = ismax ? arr[len] : 9;
    	for (int i = 0; i <= ed; i++) {
    		if (i == 9 && is4) {
    			//这里是可以直接算的哦
    			res += ismax ? (n%ten[len - 1] + 1) : ten[len - 1];
    		}
    		else {
    			res += dfs(len - 1, i == 4, ismax&&i == ed);
    		}
    	}
    	return ismax ? res : dp[len][is4] = res;
    }
    
    LL solve(LL x) {
    	int tot = 0;
    	while (x) { arr[++tot] = x % 10; x /= 10; }
    	return dfs(tot, false, true);
    }
    
    void init() {
    	memset(dp, -1, sizeof(dp));
    	ten[0] = 1;
    	for (int i = 1; i < maxn; i++) ten[i] = ten[i - 1] * 10;
    }
    
    int main() {
    	int tc;
    	scanf("%d", &tc);
    	init();
    	while (tc--) {
    		scanf("%I64d", &n);
    		printf("%I64d
    ", solve(n));
    	}
    	return 0;
    }
    

    杂七杂八

    orzorzorz

  • 相关阅读:
    [javaSE] 网络编程(浏览器客户端-自定义服务端)
    [javaSE] 网络编程(URLConnection)
    [javaSE] 网络编程(URL)
    [javaSE] IO流(FIle对象递归文件列表)
    tcping 与 telnet命令粗略使用
    让mysql监听ipv4
    shell脚本[] [[]] -n -z 的含义解析
    ansible的主机的默认配置部分
    MySQL备份与还原
    gunicorn 简介
  • 原文地址:https://www.cnblogs.com/fenice/p/5686266.html
Copyright © 2020-2023  润新知