Problem F

Problem F

Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 90 Accepted Submission(s) : 6
Font: Times New Roman | Verdana | Georgia
Font Size: ← →

Problem Description

假设:
S1 = 1
S2 = 12
S3 = 123
S4 = 1234
.........
S9 = 123456789
S10 = 1234567891
S11 = 12345678912
............
S18 = 123456789123456789
..................
现在我们把所有的串连接起来
S = 1121231234.......123456789123456789112345 678912.........
那么你能告诉我在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

 

思路:关键是在处理查询的时候 不能用遍历搜索 否则会超时 应该采用二分搜索 简化查询的时间

先打表 标记在s中第几位应该属于第几个Si 例如 第2位 应该属于s2  第3 位也属于 s3

用 a[i] 数组 标记 a[i] 代表si 的最后一位 是在 s字符串中的第几位

则有 规律 a[i]=a[i-1]+i  i>0  然后 对于输入的n 进行二分查找 判断n 在哪个 a[i]

然后 n=n-a[i-1]; 得出n在当前字符串si的第几位 ans=n%9;得出 n位 对应的 值

ps 当ans为0 时 ans应为 9

 

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
__int64 p,q,a[75001];
void quer(__int64 n)   // 二分查找 函数 通过p q r 分别指向 第一个 最后一个 以及中间
                     // 通过判断 n 与 a[r]大小 每次 缩减 1/2 个区间 直到最后 q p
    __int64 r;         // 所知的区间 相差小于等于 1
    p=0;
    q=75000;
    r=((q+p)/2);
    while(1)
    {
        if(n<a[r])
        {
            q=r;
            r=((q+p)/2);
        }
        else
        {
            p=r;
            r=((p+q)/2);
        }
    //    printf("%I64d %I64d %I64d\n",p,r,q);
        if(q-p<=1)break;
    }
}
int main()
{
    __int64 ans,n,i,k;
    a[0]=0;
    for(i=1;i<75001;i++)
    {
        a[i]=a[i-1]+i;
    }
    scanf("%I64d",&k);
//    freopen("1.txt","r",stdin);
    while(k--)
    {
        scanf("%I64d",&n);
        quer(n);
        if(n>a[p])i=q;    //判断 n 输入 p q 中的哪个区间
        else i=p;
    //    printf("%I64d\n",i);
        n=n-a[i-1];
        ans=n%9;
        if(ans==0)ans=9;
        printf("%I64d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值