代码中有详细解释,cnt要使用long long int(害我找了好久):joy:
#include <bits/stdc++.h> using namespace std; typedef long long int ll; ll m, n, cntn, cntx, dp[20][10][2]; int bit[20]; ll DFS(int pos, int remain, bool isMax, bool hasSeven) { //pos:位数, remain:上一位残留下来的余数, isMax:上一位是否达到了最大值, hasSeven记录是否位数上是否出现过7 if(pos == 0) { return (!remain) || hasSeven; } //若余数不为0,则说明不能被7整除,不计数,否则计数 if(!isMax && dp[pos][remain][hasSeven]) return dp[pos][remain][hasSeven]; //若上一位不为最大值,且相同位数、相同余数的情况已经计算过,那么直接拿来用就好 int maxNum = isMax ? bit[pos] : 9; ll cnt = 0; //上一位为最大值时,这一位的取数将受到bit[pos]的限制 for(int i = 0; i <= maxNum; i++){ //if(!hasSeven && i == 7) cnt++; cnt += DFS(pos - 1, (i + 10 * remain) % 7, isMax && i == maxNum, hasSeven || i == 7); } return isMax ? cnt : dp[pos][remain][hasSeven] = cnt; //不是最大值,把数据记录下来才有意义 } ll tran(ll num) { int pos = 0; while(num){ bit[++pos] = num % 10; num /= 10; } return DFS(pos, 0, true, false); } int main() { cin>>m>>n; cntn = tran(m);//记录到m时已经拍掌的次数 //cout<<cntn<<endl; ll ri = m + n * 7 + 7;//右边界 ll le = m; ll mid; while(le <= ri) { mid = (le + ri) / 2; if (tran(mid) - cntn >= n) { ri = mid - 1; } else { le = mid + 1; } } cout<<le<<endl; return 0; }