链接:http://poj.org/problem?id=1019
分析:就是计数的问题。。可以先算出112123...m共有多少位,具体式子看代码。。然后二分取一个最大的小于n的m,接下来考虑123...m有多少位,再二分一下求解就可以了。。具体式子还是看代码。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 typedef long long ll; 6 ll q[10],powten[11]; 7 long long p[100005]; 8 void CalQ(){ 9 powten[0]=1; 10 for(int i=1;i<=10;i++)powten[i]=powten[i-1]*10; 11 q[0]=0; 12 for(int i=1;i<=9;i++) 13 q[i]=q[i-1]+9*i*powten[i-1]; 14 } 15 ll f(int x){ 16 if(x==0)return 0; 17 int len=0,x0=x; 18 while(x0){ 19 len++;x0/=10; 20 } 21 if(len==1)return x; 22 return q[len-1]+(ll)len*(x-powten[len-1]+1); 23 } 24 void CalP(){ 25 CalQ(); 26 p[0]=0; 27 p[1]=1; 28 for(int i=2;i<100005;i++){ 29 p[i]=p[i-1]+f(i); 30 // if(i%500==0){ 31 // i=i; 32 // memset(p,0,i*sizeof(int)); 33 // } 34 } 35 } 36 int dich(int n){ 37 int l=0,r=4e4,m=(l+r)/2; 38 while(l<=r&&l!=m){ 39 ll t=p[m]; 40 if(t==n)return m-1; 41 else if(t>n)r=m; 42 else l=m; 43 m=(l+r)/2; 44 } 45 return r-1; 46 } 47 int Dich(int n){ 48 int l=0,r=n,m=(l+r)/2; 49 while(l<=r&&l!=m){ 50 int t=f(m); 51 if(t==n)return m; 52 else if(t>n)r=m; 53 else l=m; 54 m=(l+r)/2; 55 } 56 return r-1; 57 } 58 int solve(int n){ 59 int m=dich(n); 60 int h=Dich(n-p[m]); 61 int k=n-f(h)-p[m]-1; 62 if(k==-1)return h%10; 63 char str[15]; 64 sprintf(str,"%d",h+1); 65 return str[k]-‘0‘; 66 } 67 char s[1000000]; 68 //void Gets(){ 69 // s[0]=‘\0‘; 70 // char str[5]; 71 // for(int i=1;i<500;i++){ 72 // for(int j=1;j<=i;j++){ 73 // sprintf(str,"%d",j); 74 // strcat(s,str); 75 // } 76 // } 77 //} 78 //int test(int n){ 79 // return s[n-1]-‘0‘; 80 //} 81 int main(){ 82 CalP(); 83 //Gets(); 84 //freopen("e:\\out.txt","w",stdout); 85 //freopen("e:\\in.txt","r",stdin); 86 int t,n; 87 scanf("%d",&t); 88 n=1; 89 while(t--){ 90 scanf("%d",&n); 91 //int a=test(n),b=solve(n); 92 //printf("%d ",a); 93 printf("%d\n",solve(n)); 94 //if(a!=b)cout<<n<<"***************\n"<<endl; 95 } 96 return 0; 97 }
时间: 2024-10-14 16:29:02