思路:dp[i][fpre][pre][sta]表示前i为,前面两个数分别为fpre,pre,状态为sta的满足题意的个数。
二分出一个相近的数,然后一个个实验就行。
代码:
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
const int maxn=1e3+7;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int mod=1e9+7;
ll n;
ll dp[30][10][10][2];
int a[30];
ll dfs(int pos,int fpre,int pre,int sta,bool limit)
{
if(pos==-1)
{
return sta==1;
}
if(limit==0&&dp[pos][fpre][pre][sta]!=-1)
{
return dp[pos][fpre][pre][sta];
}
int up=limit?a[pos]:9;
ll ans=0;
for(int i=0;i<=up;i++)
{
ans+=dfs(pos-1,pre,i,sta||(fpre==6&&pre==6&&i==6),limit&&a[pos]==i);
}
if(limit==0) dp[pos][fpre][pre][sta]=ans;
return ans;
}
ll solve(ll x)
{
int pos=0;
while(x)
{
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,0,0,1);
}
bool check(ll x)
{
int pos=0;
int b[30];
while(x)
{
b[pos++]=x%10;
x/=10;
}
for(int i=0;i<pos;i++)
{
if(b[i]==6)
{
int cnt=1;
for(int j=i+1;j<pos;j++)
{
if(b[j]==6) cnt++;
else break;
if(cnt>=3) return true;
}
}
}
return false;
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
memset(dp,-1,sizeof(dp));
while(T--)
{
scanf("%lld",&n);
ll l=1,r=1e13+7;
ll ans=0;
while(l<=r)
{
ll mid=(l+r)/2;
if(solve(mid)>=n)
{
r=mid-1;
}
else
{
l=mid+1;
}
}
//printf("%lld\n",l);
ans=l;
while(check(ans)==0)
{
ans--;
}
printf("%lld\n",ans);
}
return 0;
}