POJ1019 数学+递推乱搞

╰+攻爆jí腚メ 2022-08-22 15:24 258阅读 0赞

有一个字符串的形式是这样的11212312341234512345612345671234567812345678912345678910123456789101112345678910……….

现在要求你写出他的第n位上的数字是什么,是数字而不是数,1 ≤ n ≤ 2147483647。

首先我们分析这个字符串可以看出它是由这些子串组成的,1,12,123,1234,12345……。

这样我们可以每个子串单独分析,我们可以看出来第i个子串比第i-1个子串多一个数i,数字i的长度为log10(i)+1,也就是是说第i个子串比第i-1个子串的长度长log10(i)+1,这样通过递推我们可以求出来每个子串的长度,然后还可以求出每个子串开始的位置。这样只要我们求出最长的子串的每一位是多少,就可以直接写出来结果了。

具体看代码。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. using namespace std;
  7. int const maxn = 33000 ;
  8. long long len[maxn]; //保存每个从1开始的子串的长度
  9. long long a[maxn]; //保存每个子串开始的位置
  10. int num[maxn*10]; //保存最长的一个子串的每一位的数字
  11. //数字n的长度为log(n)+1;
  12. void init()
  13. {
  14. memset(len,0,sizeof(len));
  15. memset(num,0,sizeof(num));
  16. memset(a,0,sizeof(a));
  17. len[1]=1;
  18. for(int i = 2 ; i < maxn ; i++)
  19. {
  20. len[i]=len[i-1]+(int)log10(1.0*i)+1;
  21. }
  22. a[1]=1;
  23. for(int i = 2 ; i < maxn ; i++)
  24. {
  25. a[i]=a[i-1]+len[i-1];
  26. }
  27. int k = 1;
  28. for(int i = 1 ; i < maxn ; i++)
  29. {
  30. int ans[30];
  31. memset(ans,0,sizeof(ans));
  32. int n = i ;
  33. int kk = 0 ;
  34. while(n)
  35. {
  36. ans[kk++]=n%10;
  37. n/=10;
  38. }
  39. while(kk)
  40. {
  41. num[k++]=ans[--kk];
  42. }
  43. if(k>=maxn*10)break;
  44. }
  45. }
  46. int main()
  47. {
  48. init();
  49. int t,n;
  50. scanf("%d",&t);
  51. while(t--)
  52. {
  53. scanf("%d",&n);
  54. int i;
  55. for(i = 1 ; i < maxn ; i++)
  56. {
  57. //cout<<a[i]<<endl;
  58. if(a[i]>=n)break;
  59. }
  60. if(a[i]==n)printf("1\n");
  61. else printf("%d\n",num[n-a[i-1]+1]);
  62. }
  63. return 0;
  64. }

发表评论

表情:
评论列表 (有 0 条评论,258人围观)

还没有评论,来说两句吧...

相关阅读

    相关 NEFU离散数学实验3-方程

    相关概念 > 递推方程是指一种递归定义,它将问题拆分成更小的子问题,并使用这些子问题的解来计算原问题的解。离散数学中,递推方程通常用于描述数列、组合问题等。 >...