POJ 1019

题目链接:http://poj.org/problem?id=1019

————————————————————————————————————————

题目思路:

觉得这不算是一个dp题,只是需要提前打表,用了一点递归的方法。

学了两个新的函数。嗯。细节部分要注意。

另外,如果能像其他人的题解中,把问题按照公式解决,那么细节问题就不需要考虑的太多,出错率也会降低。

————————————————————————————————————————

题目细节:

1、double log10(double x);  表示以10为底的对数值。

2、double pow( double x, double y );  计算x的y次幂。

3、网上找的题解,用简单公式解决问题。

————————————————————————————————————————

我的代码:

#include <iostream>
#include<stdio.h>
#include<math.h>

using namespace std;

int len[40000];
long long int sta[40000];
int _log[7];

int main()
{
    //freopen("in.in", "r", stdin);
    //freopen("out.txt","w",stdout);

    int t = 0,i = 0,n = 0,j = 0,temp = 0;
    long long int sum = 0;

    len[0] = 0;
    i = 1;
    sta[0] = 0;
    while(1)
    {
        len[i] = len[i-1] + (unsigned int)log10((double)i)+1;                                //注意本处的技巧
        sta[i] = sta[i-1]+len[i];
        sum += len[i];
        i++;
        if(sum>= 2147483647)
          break;
    }
    n = i;
    _log[1] = 10;
    for(i = 2;i<=5;i++)
      _log[i] = 10*_log[i-1];
    _log[0] = 1;

    scanf("%d",&t);
    while(t--)
    {
       scanf("%d",&i);
       for(j = 0;j<n;j++)
         if(i<=sta[j])
           break;
       i = i-sta[j-1];

       for(j = 1;j<=4;j++)                                                       //这里一开始的4处写的是5,故大数部分的答案是错误的。
       {
           if(i<=len[_log[j]-1])
             break;
       }

       i = i-len[_log[j-1]-1];
       temp = i%j;
       i = i/j;
       if(temp == 0)
       {
            i = _log[j-1]+i-1;
            temp = 1;
       }
       else
       {
            i = _log[j-1]+i;
            temp = j+1-temp;
       }

       while(temp--)
       {
           j = i%10;
           i = i/10;
       }
       printf("%d\n",j);
    }

    return 0;
}
网上的代码:
#include <iostream>
#include <cmath>
 
using namespace std;
 
unsigned int a[31270], s[31270];
 
/* 打表 */
void reset()
{
    int i;
    a[1] = 1;
    s[1] = 1;
    for(i = 2; i < 31270; i++)
    {
        /* 每一组数字都比上一组长 (int)log10((double)i) + 1 */
        a[i] = a[i-1] + (int)log10((double)i) + 1;
        s[i] = s[i-1] + a[i];
    }
}
 
/* 计算 */
int work(int n)
{
    int i = 1;
    int length = 0;
 
    /* 找到 n 所在的组 */
    while (s[i] < n) i++;
 
    /* n 在该组的下标 */
    int pos = n - s[i-1];
 
    /* length: n指向的数字的最后一位的下标 */
    for (i = 1; length < pos; i++)
    {
        length += (int)log10((double)i) + 1;
    }
 
    /* 去掉所求位后面的数字然后取余 */
    /* i: n指向的数字 + 1 */
    return ((i-1) / (int)pow((double)10, length - pos)) % 10;
}
 
int main()
{
    int t;
    unsigned int n;
    reset();
    cin >> t;
    while(t--)
    {
        cin >> n;
        cout << work(n) << endl;
    }
    //system("pause");
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值