1. 程式人生 > 實用技巧 >明七暗七

明七暗七

題目描述

今天是個特殊的日子,CSL和他的小夥伴們圍坐在一張桌子上玩起了明七暗七的遊戲。遊戲規則是這樣的:

一個人報出一個起始數,接下來按照逆時針的順序輪流報數,如果碰到數是7的倍數或含有7,則拍手,下一個人接著報數。直到有一個人報錯了數字或者沒有及時拍手為止。

玩遊戲嘛,當然得有懲罰。這麼簡單的遊戲對CSL的學霸小夥伴而言實在是太無腦了,輕輕鬆鬆數到上萬根本不在話下。但是對於數學是體育老師教的CSL來說,實在是太難了。快幫他算算什麼時候應該拍手吧。

輸入描述:

輸入兩個整數m和n。(1 ≤ m, n ≤ 1012)

輸出描述:

輸出一個整數,表示m以後第n個需要拍手的數字。

輸入

30 7

輸出

57

輸入

56 1

輸出

57
#include<bits/stdc++.h>
using namespace std;
const int N = 20;
typedef long long LL;
LL dim[N], dp[N][10][2];
LL dfs(int pos, int sum, int f, int lim) {
    if (pos < 0) return (!sum || f);
    if (!lim && ~dp[pos][sum][f]) return dp[pos][sum][f];
    
int up = lim ? dim[pos] : 9; LL ret = 0; for (int i = 0; i <= up; i++) { ret += dfs(pos - 1, (sum * 10 + i) % 7, f || i == 7, lim && i == up); } if (!lim) dp[pos][sum][f] = ret; return ret; } LL solve(LL x) { memset(dp, -1, sizeof(dp)); memset(dim, 0, sizeof(dim));
int len = 0; while (x) { dim[len++] = x % 10; x /= 10; } return dfs(len - 1, 0, 0, 1); } int main() { LL m, n; cin >> m >> n; LL st = solve(m); LL l = 0, r = 1e18, ret; while (l <= r) { LL k = (l + r) >> 1; LL temp = solve(k); if (temp >= st + n) r = k - 1, ret = k; else l = k + 1; } printf("%lld\n", ret); return 0; }