计数时不要某个数字,求数字对应的序号或者求某个序号对应的数字
解决方式是记忆化搜索
long long 是肯定的,并注意n最大时对应的答案的范围
原来1000000000000000000 < pow(2.0,62)……
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;
#define ll long long
ll dp[2][20];
int num[20];
ll dfs(int cur,bool ok,int pre) // ok is no limit or not,pre is 1 previous or not
{
if(ok && dp[pre][cur]!=-1)
return dp[pre][cur];
if(cur==0)
return 1;
ll ret=0;
for(int i=0;i<10;++i)
{
if(!ok && i>num[cur])
break;
if(pre && i==3)
continue;
if(!ok && i==num[cur])
ret+=dfs(cur-1,false,i==1?1:0);
else
ret+=dfs(cur-1,true,i==1?1:0);
}
if(ok)
return dp[pre][cur]=ret;
else return ret;
}
int main ()
{
int test;scanf("%d",&test);
memset(dp,-1,sizeof(dp));
while(test--)
{
ll n;cin>>n;
int cnt=0;
ll left=0,right=2000000000000000000;
while(left<right)
{
ll mid=(left+right)/2;
ll k=mid;
int cnt=0;
while(k)
{
num[++cnt]=k%10;
k/=10;
}
ll res=dfs(cnt,false,0);
res--;
if(res>=n)
right=mid;
else left=mid+1;
}
cout<<left<<endl;
}
return 0;
}