题意:
求第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
*/

本文介绍了一种求解特定序列第n个元素的方法,利用二分搜索和数位动态规划技术,解决数学问题。
1028

被折叠的 条评论
为什么被折叠?



