hdu1597(规律)

43 篇文章 0 订阅

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个数字是多少吗?
 

Input
输入首先是一个数字K,代表有K次询问。
接下来的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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bokzmm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值