题意:
求第n个Bnumber。
题解:
我们可以二分枚举答案,判断是否满足条件,通过二分不断往正确解缩进。那么问题就变成求n以内的数包含了多少Bnumber,这个很明显是用数位dp求解,先求出Anumber的个数,然后减去不满足的数就是Bnumber的个数,处理有一点小技巧。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #define B(x) (1<<(x)) using namespace std; typedef long long ll; typedef unsigned long long ull; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } void cmax(ll& a,ll b){ if(b>a)a=b; } void cmin(ll& a,ll b){ if(b<a)a=b; } void add(int& a,int b,int mod){ a=(a+b)%mod; } void add(ll& a,ll b,ll mod){ a=(a+b)%mod; } const int oo=0x3f3f3f3f; const int MOD=2012; ull dp[22][11][2]; bool vis[22][11][2]; int bit[22]; ull dfs(int pos,int sum,int is,int f){ if(pos<1) return (sum==0||is); if(!f&&vis[pos][sum][is]) return dp[pos][sum][is]; int last= f ? bit[pos] : 9; ull res=0; for(int i=0;i<=last;i++){ res+=dfs(pos-1,(sum*10+i)%7,is||i==7,f&&i==last); } if(!f){ dp[pos][sum][is]=res; vis[pos][sum][is]=true; } return res; } ull Cnt(ull n){ int len=0; ull m=n; while(m){ bit[++len]=m%10; m/=10; } return dfs(len,0,0,1)-1; } ull fcnt(ull n){ ull ans=Cnt(n); return ans-Cnt(ans); } ull solve(ull n){ ull l=1,r=(ull)11000000000000000000; while(l<=r){ ull mid=(l+r)>>1; ull t=fcnt(mid); if(t>=n) r=mid-1; else l=mid+1; } return l; } int main(){ //freopen("E:\\read.txt","r",stdin); ull n; memset(vis,false,sizeof vis); while(scanf("%llu",&n)!=EOF){ cout<<solve(n)<<endl; } return 0; } /** 11000000000000000000 */