uva12486 Space Elevator(数位dp)

转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

 

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

 

题意:问第n个各个数位上不出现连续的13和4的数是多少?从1开始算,n<=10^18

莫名奇妙地写跪了,重写一发就过了、、、

可以比较容易的得出小于等于x的满足那些要求的数有多少个,然后根据这个二分。直接二分答案。

注意需要用unsigned long long

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author xyiyy @https://github.com/xyiyy
 */

#include <iostream>
#include <fstream>

//#####################
//Author:fraud
//Blog: http://www.cnblogs.com/fraud/
//#####################
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>

using namespace std;
#define rep(X, N) for(int X=0;X<N;X++)
#define dep(X, R, L) for(int X=R;X>=L;X--)
typedef unsigned long long ull;

typedef unsigned long long ull;
ull dp[30][10];
int d[30];

class TaskE {
public:
    void solve(std::istream &in, std::ostream &out) {
        //bign n;

        rep(i, 30)
            rep(j, 10)dp[i][j] = 0;
        run();
        ull n;
        while (in >> n) {
            ull ans = 1;
            ull l = 1;
            ull r = -1;
            while (l <= r) {
                int f = 0;
                if ((l & 1) && (r & 1))f++;
                ull mid = (r >> 1) + (l >> 1) + f;
                if (gao(mid) <= n) {
                    ans = mid;
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }
            out << ans << endl;
        }
    }

    ull gao(ull n) {
        ull ans = 0;
        int len = 0;
        while (n) {
            d[++len] = n % 10;
            n /= 10;
        }
        d[len + 1] = 0;
        dep(i, len, 1) {
            rep(j, d[i]) {
                if (d[i + 1] != 1 || j != 3) {
                    ans += dp[i][j];
                }
            }
            if (d[i] == 4 || (d[i + 1] == 1 && d[i] == 3))break;
        }
        return ans;
    }

    void run() {
        dp[0][0] = 1;
        for (int i = 1; i <= 20; i++) {
            for (int j = 0; j <= 9; j++) {
                for (int k = 0; k <= 9; k++) {
                    if (j != 4 && !(j == 1 && k == 3)) {
                        dp[i][j] += dp[i - 1][k];
                    }
                }
            }
        }
    }
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    TaskE solver;
    std::istream &in(std::cin);
    std::ostream &out(std::cout);
    solver.solve(in, out);
    return 0;
}

 

posted on 2015-08-14 21:18  xyiyy  阅读(123)  评论(0编辑  收藏  举报

导航