hihoCoder #1301 : 筑地市场 (打表+构造)
题目大意:问含有4或者7的第k大的正数是多少。
题目分析:1~10、1~100、1~1000...之间的含有4或者7的个数可以求出,这样就可以从高位到地位依次确定这个数的每一位上的值。
代码如下:
# include<iostream> # include<cstdio> using namespace std; # define LL long long # define uLL unsigned long long uLL a[20]={2,36,488,5904,67232,737856,7902848, 83222784,865782272,8926258176,91410065408, 931280523264,9450244186112,95601953488896, 964815627911168,9718525023289344, 97748200186314752,981985601490518016 }; uLL b[20][10]; uLL n; void init() { for(int i=0;i<10;++i){ if(i==4||i==7) b[0][i]=10; else b[0][i]=2; } for(int i=1;i<18;++i){ for(int j=0;j<10;++j){ if(j==4||j==7) b[i][j]=b[i-1][j]*10; else b[i][j]=a[i]; } } } int main() { init(); cin>>n; uLL ans=0; int cnt=0; while(n>0){ if(n<=2){ if(n==1) ans+=4; else ans+=7; break; } int k=17; while(k>=0&&n<=a[k]) --k; cnt=0; while(cnt<10&&n>b[k][cnt]){ n-=b[k][cnt]; ++cnt; } uLL res=cnt; for(int i=0;i<=k;++i) res*=10; ans+=res; if(cnt==4||cnt==7){ ans+=n-1; break; } } cout<<ans<<endl; return 0; }
打表代码:
# include<iostream> # include<cstdio> using namespace std; # define LL long long # define uLL unsigned long long int main() { uLL k=10; uLL a=2,b=20; int cnt=1; while(k<=1000000000000000000) { cout<<(cnt++)<<' '<<a<<' '<<k<<endl; a=a*8+b; b*=10; k*=10; } cout<<(cnt++)<<' '<<a<<' '<<k<<endl; return 0; }