http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2609
A-Number and B-Number
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
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
输入
The input consists of multiple test cases.
For each test case, there will be a positive integer N as the description.
输出
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.
示例输入
1 7 100
示例输出
7 37 470
提示
来源
2013年山东省第四届ACM大学生程序设计竞赛
示例程序
分析:
一开始想到打表,结果超时咯,后来看了标程用了搜索写的,,,orz
超时代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 bool fun(int n){ 6 if(n%7==0) return true; 7 while(n) { 8 if(n%10==7) return true; 9 n/=10; 10 } 11 return false; 12 } 13 long long a[100000010]; 14 long long b[100010000]; 15 int main(){ 16 int i,c=0,cc=0; 17 //freopen("in.txt","r",stdin); 18 for(i=1;i<=100000000;i++) 19 if(fun(i)) a[++c]=i; 20 for(i=1;i<c;i++) 21 if(!fun(i)) 22 { b[++cc]=a[i];} 23 long long n; 24 while(cin>>n){ 25 if(n>cc-1) cout<<"??"; 26 else 27 cout<<b[n]<<endl;} 28 return 0; 29 }
官方标程:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define ULL unsigned long long 6 const ULL Maxn=((1uLL<<64uLL)-1); 7 ULL dp[22][10][2]; 8 int digit[24]; 9 ULL dfs(int pos,int pre,int flag,bool limit){ 10 if(pos==-1) return flag||pre==0; 11 if(!limit&&dp[pos][pre][flag] != -1) return dp[pos][pre][flag]; 12 int end = limit?digit[pos]:9; 13 int fflag,ppre; 14 ULL ans=0; 15 for(int i = 0;i <= end;i++){ 16 fflag = (i==7)||flag; 17 ppre=(pre*10+i)%7; 18 ans+=dfs(pos-1,ppre,fflag,limit&&i==end); 19 } 20 if(!limit) dp[pos][pre][flag]=ans; 21 return ans; 22 } 23 ULL solve(ULL n){//找到n以下有几个A-number 24 int pos = 0; 25 while(n){ 26 digit[pos++] = n%10; 27 n /= 10; 28 if(!n) break; 29 } 30 return dfs(pos-1,0,0,1)-1; 31 } 32 ULL find(ULL n){//找到n以下有几个B-number 33 ULL t = solve(n);//表示n包括n以下在A中有t个 34 ULL tt = t - solve(t);//表示t(包括第t个)个A_number中有几个是符合在B中的,一直找到tt刚好等于n为止 35 return tt; 36 } 37 int main() 38 { 39 memset(dp,-1,sizeof(dp)); 40 ULL n; 41 while(cin>>n){ 42 ULL l = 0, r= Maxn,mid; 43 while(l <= r){ 44 mid = ((r-l)>>1)+l; 45 if(find(mid)<n) l = mid+1; 46 else r = mid-1; 47 } 48 ULL ans = r+1; 49 cout<<ans<<endl; 50 } 51 return 0; 52 }