明七暗七
题目描述
今天是个特殊的日子,CSL和他的小伙伴们围坐在一张桌子上玩起了明七暗七的游戏。游戏规则是这样的:
一个人报出一个起始数,接下来按照逆时针的顺序轮流报数,如果碰到数是7的倍数或含有7,则拍手,下一个人接着报数。直到有一个人报错了数字或者没有及时拍手为止。
玩游戏嘛,当然得有惩罚。这么简单的游戏对CSL的学霸小伙伴而言实在是太无脑了,轻轻松松数到上万根本不在话下。但是对于数学是体育老师教的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; }

浙公网安备 33010602011771号