find the nth digit
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10155 Accepted Submission(s): 2988
Problem Description
假设:
S1 = 1
S2 = 12
S3 = 123
S4 = 1234
.........
S9 = 123456789
S10 = 1234567891
S11 = 12345678912
............
S18 = 123456789123456789
..................
现在我们把所有的串连接起来
S = 1121231234.......123456789123456789112345678912.........
那么你能告诉我在S串中的第N个数字是多少吗?
S1 = 1
S2 = 12
S3 = 123
S4 = 1234
.........
S9 = 123456789
S10 = 1234567891
S11 = 12345678912
............
S18 = 123456789123456789
..................
现在我们把所有的串连接起来
S = 1121231234.......123456789123456789112345678912.........
那么你能告诉我在S串中的第N个数字是多少吗?
Input
输入首先是一个数字K,代表有K次询问。
接下来的K行每行有一个整数N(1 <= N < 2^31)。
接下来的K行每行有一个整数N(1 <= N < 2^31)。
Output
对于每个N,输出S中第N个对应的数字.
Sample Input
6 1 2 3 4 5 10
Sample Output
1 1 2 1 2 4解题思路:s1=1;s2=12;s3=123;s4=1234;......s=s1+s2+s3+s4+s5+...........首先,由题意可知串S的包含的数的个数等于1+2+3+4+.....n=n*(n+1)/2.即串S所包含数的个数等于等差数列前n项和。这样就有规律可循啦。可以发现:对于串S中第N个对应的数字就是:如果[N-i*(i+1)/2]%9==0那么就是9,否则就是 [N-i*(i+1)/2]%9.其中,i就是当i*(i+1)/2小于n的最大的i.就是找到小于N且离N最近的前i项的和(即前i项的包含数的个数).为什么要减去前i项的和呢?假如N对应那个的数在s8组成的的序列内,其实减去就是s1,s2,s3,s4,s5,s6,s7的包含数的个数总和,(即等差数列前7项和)减去之后就只剩下s8啦。然后根据对9取余就可以判断其对应的数字。例如:N=10时,可知i=3,[10-3*(3+1)/2]%9=4,所以对应第十个为4.N=171时,可知i=17,[171-17*(17+1)/2]%9==0,所以对应第171个为9.不过思路容易想,关键是如何求最接近N的前i项和。这一点真是坑,写了半天不是超时就是wa.最后看了讨论区的有位小伙思路不错;值得膜拜。就是令 i*(i+1)/2=n解一元二次方程可得i=sqrt(0.25+2*n)-0.5;可以大致确定i;让后用个循环找出大于N的第一个前i项和,最后i=i-1;就是所要找的i.AC代码:#include<stdio.h> #include<math.h> int main() { __int64 n,m,i,j,k,t; scanf("%I64d",&t); while(t--) { scanf("%I64d",&n); double x=sqrt(0.25+2.0*n)-0.5;i=x; //利用求根公式求得i while(i*(i+1)/2<n) i++; //为了精确,找到大于N的前i项和.对应的i. k=i*(i-1)/2; //计算出小于N的前i项和。 if((n%k)%9==0) printf("9\n"); else printf("%d\n",(n%k)%9); } return 0; }