• poj 1019 Number Sequence 【组合数学+数字x的位宽函数】


    题目地址:http://poj.org/problem?id=1019

    Number Sequence
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 35680   Accepted: 10287

    Description

    A single positive integer i is given. Write a program to find the digit located in the position i in the sequence of number groups S1S2...Sk. Each group Sk consists of a sequence of positive integer numbers ranging from 1 to k, written one after another.
    For example, the first 80 digits of the sequence are as follows:
    11212312341234512345612345671234567812345678912345678910123456789101112345678910

    Input

    The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by one line for each test case. The line for a test case contains the single integer i (1 ≤ i ≤ 2147483647)

    Output

    There should be one output line per test case containing the digit located in the position i.

    Sample Input

    2
    8
    3

    Sample Output

    2
    2
    分析:序列如上所示,要求这个序列的第n位是什么,首先需要知道的是:一个数x的宽度怎么算?可以每次让x除10,看看多少次可以除尽。
    不过比较麻烦,有简单的算法:f[x]=log10(x)+1; 999的位宽=log10(999)+1=3;
    有了这个就可以来想怎么解决上面的问题。
    参考博客1:http://www.cnblogs.com/ACShiryu/archive/2011/08/05/2129009.html
    参考博客2:http://blog.csdn.net/lyy289065406/article/details/6648504
    一个大序列可以划分成许多个有规律的子序列,先找到第n位在那个子序列上,再找到在子序列的那个数字上,再找到在该数字的哪一位上。
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <math.h>
    #include <cmath>
    #include <iostream>
    #include <string>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    #define N 100000+100
    
    using namespace std;
    long long int f[40000];
    long long int s[40000];
    int main()
    {
        int i, j;
    
        memset(f, 0, sizeof(f));
        memset(s, 0, sizeof(s));
    
        long long int sum=0;
        f[1]=1; s[1]=1;
        i=2;
        while( i<=31269 )
        {
            f[i]=f[i-1]+(int)log10((double)i)+1;
            s[i]=s[i-1]+f[i];
            i++;
        }//打表
    
        int tg; scanf("%d", &tg);
        while(tg--){
            int n;
            scanf("%d", &n);
            for(i=1; i<=31269; i++){
                if(s[i]>=n) break;
            }
            int pos=i; //找到在第pos个子序列上
            n=n-s[pos-1];
            for(j=1; j<=pos; j++){
                n=n-((int)log10((double)j)+1); //减去当前这个数的宽度
                if(n<=0){
                    break;
                }
            }
            int pos2=j;//找到在子序列的第pos2个数上
            n=n+(int)log10((double)pos2)+1;//在这个数的第n位上
    
            int dd=(int)log10((double)pos2)+1-n;
            int q=1, w=1;
            for(i=1; i<=dd; i++) {q=q*10; w=w*10;} w=w*10;
    
            int ans;
            ans=pos2%w/q;
            printf("%d
    ", ans );//输出结果
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    SQLServer多表联查,多表分页查询
    GOF23种设计模式概括
    常用的正则表达式
    面向对象七大原则
    Jquery简单学习
    MVC图片上传详解
    面向对象OOP概念描述
    C++ 基础命名空间 using namespace std;
    找不到WJSWDLL.dll
    AspectJ中的类型间声明(成员注入)
  • 原文地址:https://www.cnblogs.com/yspworld/p/4693739.html
Copyright © 2020-2023  润新知