UVA 12486 Space Elevator(数位DP)

题目pdf:http://acm.bnu.edu.cn/v3/external/124/12486.pdf

大致题意:求第n个不包含"4"和"13"为子串的数是多少 , n<= 1e18

思路:就是一般的数位DP,二分答案,对答案的数求数位DP算出此数以内有多少个满足条件的数

但是....居然答案爆long long,要用unsigned long long 才能过,就这个坑点

// 0 ms 0 KB 2633 B 2015-08-15 01:02:36
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
#define rep(i,n) for ( int i=0; i< int(n); i++ )
using namespace std;
typedef unsigned long long ull;
#define X first
#define Y second
typedef pair<int,int> pii;

template <class T>
inline bool RD(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void PT(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) PT(x / 10);
    putchar(x % 10 + '0');
}

ull dp[20][3];
/*
 dp[i][0] 不包含4和13
 dp[i][1] 不包含4和13最高位为3
 dp[i][2] 包含4或13
 */
int bit[20];
ull cal(ull x){
        ull t = x;
        int c = 0;
        while(t){
                bit[++c] = t%10;
                t /= 10;
        }
        bit[c+1] = 0;
        ull ans = 0;
        bool is_13 = 0;
        for(int p = c; p >= 1; p--){
                ans += bit[p]*dp[p-1][2];
                if(is_13) ans += bit[p]*dp[p-1][0];
                else{
                        if(bit[p] > 4) ans += dp[p-1][0];
                        if(bit[p] > 1) ans += dp[p-1][1];
                        if(bit[p+1] == 1 && bit[p] > 3) ans += dp[p-1][0];
                        if( (bit[p+1] == 1 && bit[p] == 3)||bit[p] == 4)is_13 = 1;
                }
        }
        return x-ans;
}
int main(){
        dp[0][0] = 1;
        REP(i,18){
                dp[i][0] = dp[i-1][0]*9-dp[i-1][1];
                dp[i][1] = dp[i-1][0];
                dp[i][2] = dp[i-1][2]*10+dp[i-1][0]+dp[i-1][1];
        }

        ull n;
        while(RD(n)){
                ull lb = 0,ub = (ull)1000000000000000000*18;
                while(ub-lb > 1){
                        ull mid = lb/2 + ub/2 + ((lb&1)+(ub&1))/2;
                        if(cal(mid) <= n) lb = mid;
                        else ub = mid;
                }
                PT(lb);puts("");
        }

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-24 01:16:35

UVA 12486 Space Elevator(数位DP)的相关文章

BNU 26351 Space Elevator 数位dp

Problem E Space Elevator China is building a space elevator, which will allow the launching probes and satellites to a much lower cost, enabling not only scienti?c research projects but also space tourism. However, the Chinese are very superstitious,

uva 417 - Word Index(数位dp)

题目连接:uva 417 - Word Index 题目大意:按照题目中的要求,为字符串编号,现在给出字符串,问说编号为多少,注意字符串必须为递增的,否则编号为0. 解题思路:其实就是算说比给定字符串小并且满足递增的串由多少个.dp[i][j]表示第i个位为j满足比给定字符串小并且满足递增的串. dp[i][j]=∑k=0j?1dp[i?1][k]. 注意每次要处理边界的情况,并且最后要加上自身串.并且在处理边界的时候dp[i][0]要被赋值为1,代表前i个为空的情况. #include <cs

UVa 1009 Sharing Chocolate (数位dp)

题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3540 题目大意: 给一块长x,宽y的巧克力,和一个数组A={a1, a2, …,an},问能否经过若干次切分后,得到面积分别为a1,a2,…an的n块巧克力.每次切分只可以选择一块巧克力,将其分为两半,如下图,3×4的巧克力经过切分后,可以得到面积分别为6,3,2,1的巧克力.

POJ 2392 Space Elevator 贪心+dp

题目链接: http://poj.org/problem?id=2392 题意: 给你k类方块,每类方块ci个,每类方块的高度为hi,现在要报所有的方块叠在一起,每类方块的任何一个部分都不能出现在ai以上的高度,问这些方块能叠的最高高度. 题解: 首先按ai升序排序,尽量让高度限制低的先排掉,如果不这样做一些转移会失效掉: 比如:h1=3,a1=3;h2=4,a2=7 如果先搭1再搭2则合法,但反过来则变成无效的转移了. 处理好顺序之后跑一遍背包就可以了,因为最大高度为40000,比较小,所以用

uva 1489 - Math teacher&#39;s homework(数位dp)

题目链接:uva 1489 - Math teacher's homework 题目大意:给定n,k,以及序列m1,m2,-,mn, 要求找到一个长度为n的序列,满足0<=xi<=mi, 并且x1XORx2XOR-XORxn=k 解题思路:数位dp,在网上看了别人的代码,高大上... 假设有二进制数 k : 00001xxxx mi:0001xxxxx, 那么对于xi即可以满足任意的x1XORx2XOR-XORxi?1XORxi+1XOR-XORxn,根据这一点进行数位dp. dp[i][j]

uva 11361 Investigating Div-Sum Property 数位dp

// uva 11361 Investigating Div-Sum Property 数位dp // // 题目大意: // // 给你一个整数a和一个整数b,问在[a,b]范围内,有多少个自身被k整除并且 // 各位数之和也能被k整除.比如k = 7 ,322满足条件,因为332能被整除7,并 // 3 + 2 + 2 = 7 也能被7整除 // // 解题思路: // // 求一个区间的题目,这类题目,往往可以转化为不超过x的f(x).则最后要求 // 的就是f(b) - f(a-1).如

UVA 11361 - Investigating Div-Sum Property(数位DP)

题目链接:11361 - Investigating Div-Sum Property 白书上的例题,不过没有代码,正好前几天写了一题数位DP的题目,这题也就相对轻松了. dp[i][x][y]表示加到第i位,数字 % k,数位和 % k的组合情况数,那么现在要添加一个0 - 9的数字上去状态转移为 dp[i + 1][(x * 10 + num) % k][(y + num) % k],计算总和后,由于数字本身不能超过最大值,所以最后还要添加上恰好前几位都为最大值的情况.然后最后在判断一下该数

uva 10712 - Count the Numbers(数位dp)

题目链接: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 na

UVA - 11038 How Many O&#39;s? (数位dp)

How Many O's? 题意是求区间内数字中0的个数,比如100就有两个0. 数位dp吧,dp[i][j][k], i很明显表示当前位置,j表示找到的0的个数,k表示要找的0的个数.因为数字里0的个数最多32个,所以可以枚举32种k的情况,用数位dp去找. #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #