poj1019 递推关系

给定一个序列有如下特征:
1.S1S2…Sk
2.每一组子序列Sk为:1,2,……,k
例如:11212312341234512345612345671234567812345678912345678910123456789101112345678910 (长度为80)
现给定一个数n,输出上述序列第n个“字符”是多少。
AC/216K/0MS

#include<iostream>
using namespace std;
int c[10];  //存放n的十进制,c[0]记录长度
long long b[35000],a[6];
int m[6]={1,10,100,1000,10000,100000};  //m[i]表示i+1位数字中最小的数

/*计算所有小于等于n并且和n具有相同位数的数组成的序列的总长度*/
int work(int n)
{
    c[0]=0;
    while(n)
    {
        c[++c[0]]=n%10;
        n/=10;
    }
    int sum=0;
    for(int i=c[0];i>0;i--)
    {
        int t=c[i];
        if(i==c[0]) t--;
        sum+=t*m[i-1];
    }
    return (sum+1)*c[0];
}

/*打表计算序列S1S2...Sk的长度并存入b[k]中*/
void play_table()
{
    int i,k=1;

    /*a[i]记录所有长度小于等于i的数组成的序列的总长度*/
    a[0]=0;
    for(i=1;i<6;i++)
    {
        a[i]=(k*10-k)*i;
        a[i]+=a[i-1];
        k*=10;
    }


    b[0]=0;
    for(i=1;i;i++)
    {
        b[i]=work(i);
        b[i]+=a[c[0]-1];
        b[i]+=b[i-1];
        if(b[i]>2147483647) break;
    }
}

/*计算m的第n位数字*/
int caclu(int m,int n)
{
    c[0]=0;
    while(m)
    {
        c[++c[0]]=m%10;
        m/=10;
    }
    return c[c[0]-n+1];
}

/*计算第n个数字*/
int solve(int n)
{
    int i;

    for(i=0;i>=0;i++)
        if(b[i]<n&&b[i+1]>=n)   break; 
        //满足条件时跳出,位于子序列S(i+1)中

    n-=b[i];
    for(i=0;i>=0;i++)
        if(a[i]<n&&a[i+1]>=n)    break;
    n-=a[i]; i++;
    int ans=m[i-1]+(n-1)/i; //第n个数字是ans的第n-((n-1)/i)*i位数
    return caclu(ans,n-((n-1)/i)*i);
}
int main()
{
    play_table();
    int t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        cout<<solve(n)<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值