题目链接:hrbust的oj上有题目
————————————————————————————————
A-Number and B-Number
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 22(8 users) Total Accepted: 5(5 users) Rating: Special Judge: No
Description
Tom is very interested in number problem. Nowadays he is thinking of a problem about A-number and B-number.
A-number is a positive integer whose decimal form contains 7 or it can be divided by 7. We can write down the first 10 A-number ( a[i] is the ith A-number)
{a[1]=7,a[2]=14,a[3]=17,a[4]=21,a[5]=27,a[6]=28,a[7]=35,a[8]=37,a[9]=42,a[10]=47};
B-number is Sub-sequence of A-number which contains all A-number but a[k] ( that k is a A-number.) Like 35, is the 7th A-number and 7 is also an A-number so the 35 ( a[7] ) is not a B-number. We also can write down the first 10 B-number.
{b[1]=7,b[2]=14,b[3]=17,b[4]=21,b[5]=27,b[6]=28,b[7]=37,b[8]=42,b[9]=47,b[10]=49};
Now Given an integer N, please output the Nth B-number.
Input
The input consists of multiple test cases.
For each test case, there will be a positive integer N as the description. (0<N<263−1)
Output
For each test case, output an integer indicating the Nth B-number.
You can assume the result will be no more then 2^63-1.
Sample Input
1
7
100
Sample Output
7
37
470
——————————————————————————————————
题目大意:
A数组就是民间游戏”敲七”的序列
B数组就是
{x∣∣xi∈{A}且i∉{A}}
然后输出B数组中第n个元素即:
Bn
解题思路:
如果直接求第i个元素的话 无论是A数组还是B数组都不能求(反正我不会)
但是他求得是第 i 个元素 我们可以换一个角度来思考
首先我们可以用一个入门级别的数位dp来统计小于
那么反过来 [1,n]中 最小的有x个元素的n 就是第x个元素
那么我们就可以用二分答案来统计了
对于A数组我们很好数位dp
但是对于B数组我们不能直接求出来
但是考虑A与B数组的关系,发现,只要对cal(x)统计的结果ans在统计一下相减即可;
即:
A = cal(x);
B = A - cal(A);
注意
二分溢出的问题
最大值要(1<<63)-1,
附本题代码
——————————————————————————————————————————————
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
/********************************/
int num[20];
LL dp[20][8][2];
LL dfs(int pos,int mod,int limit,int status){
if(pos<0) return (status||mod%7==0);
if(dp[pos][mod][status]!=-1&&!limit) return dp[pos][mod][status]; //忘写 limit 懵逼1000天有没有
int endi=9;
if(limit) endi=num[pos];
LL res = 0;
for(int i=0;i<=endi;i++)
res+=dfs(pos-1,(mod*10+i)%7,limit&&i==endi,i==7||status);
if(!limit) dp[pos][mod][status] = res;
return res;
}
LL cal(LL x){
if(!x) return 0;
int len=0;
while(x) num[len++]=x%10,x/=10;
return dfs(len-1,0,1,0)-1;
}
void solve(LL x){
LL l=7,r=(1ll<<63)-1,mid,ans=-1; //r写成1e18 wa懵逼有没有,,,,
while(l<=r){
mid=((r-l)>>1)+l;
LL tmp = cal(mid);
tmp -= cal(tmp);
if(tmp>=x)ans=mid,r=mid-1;
else l=mid+1;
}
printf("%lld\n",ans);
}
int main(){
// printf("%lld\n",~(1ll<<63));
memset(dp,-1,sizeof(dp));
LL n;
while(~scanf("%lld",&n)) solve(n);
return 0;
}