题意:
就是说一群人做一圈,轮流从1开始报数,如果这个数字包含7或者是7的倍数那么就拍一次手。现在问你数n以后,第m次拍手的时候的数字应该是多少。
思考:
看了看,不像思维题,再一看,这明显就是数位dp了,然后问你什么时候第m拍手,那就二分看看什么时候满足。当时傻逼了,是n以后,我以为包含n,一直错。
其实呢,当时还是在怀疑是不是自己的dp限制加少了,其实,我们考虑的是是否为7的倍数,是否包含7,只要这两个限制有了,就是满足的。就是只要dp里面包含所有题目要求限制的东西,那么就是不会多算和少算的。是否为7的倍数,我们用当前%7的值是多少来限制,是否包含7就用suc来限制。
代码:
int T,n,m,k;
int va[N];
int dp[20][20][2];
int dfs(int pos,int limit,int lead,int sum,int suc)
{
if(!pos) return (sum%7==0||suc);
if(!limit&&!lead&&dp[pos][sum][suc]!=-1) return dp[pos][sum][suc];
int res = 0;
int up = limit?va[pos]:9;
for(int i=0;i<=up;i++)
{
int limit_t = limit&&(i==up);
int lead_t = lead&&(i==0);
int sum_t = (sum*10+i)%7;
int suc_t = suc||(i==7);
res += dfs(pos-1,limit_t,lead_t,sum_t,suc_t);
}
if(!limit&&!lead) dp[pos][sum][suc] = res;
return res;
}
int f(int x)
{
mem(dp,-1);
int pos = 0;
while(x) va[++pos] = x%10,x/=10;
return dfs(pos,1,1,0,0);
}
bool check(int mid)
{
if(f(mid)-f(n)>=m) return true;
return false;
}
signed main()
{
IOS;
cin>>n>>m;
int l = n,r = 1e15;
while(l<r)
{
int mid = l+r>>1;
if(check(mid)) r = mid;
else l = mid+1;
}
cout<<l;
return 0;
}
总结:
多多思考啊,注意题目细节。