POJ 1019 许久之前,觉得这真是一道神题呢。。 递推+二分

来源:互联网 发布:无线网络连接软件下载 编辑:程序博客网 时间:2024/04/29 13:32

11212312341234512345612345671234567812345678912345678910123456789101112345678910

给出一串有以上规律的数字,找出第 n 个位置上的数字是几。

我们把这串字符串分一下

dp[i] 代表从 1 开始 结尾为 i 的子串的长度

sum[i] 代表从 1 开始到 i 子串长度的总和。

这样,我们首先确定这是到哪一个子串的,lower_bound 一下 sum,

然后我们就知道了 他在子串中的哪一个位置。

dp中保留了这个信息,在 lower bound 一下 dp.

我们就得到了一个数字,以及在这个数字中的位置。。

由于实在懒,怕错(%要从后往前,我们数位置从前往后(理论上 从前往后的第 i 个 = 从后往前的 length -i+1 个)),直接写了个函数来判断是不是到了这个位置。。

#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;#define MAX 31952#define INF 0x3f3f3f3f#define MS(x) memset(x,0,sizeof(x))#define ll long longll dp[50000];ll sum[50000];ll len(ll n){ll ans=0;while(n)ans++,n/=10;return ans;}int main(){dp[1]=1;sum[1]=1;int i;for(i=2;i<MAX;i++){dp[i]=dp[i-1]+len(i);sum[i]+=sum[i-1]+dp[i];}ll num;int T;cin>>T;while(T--){cin>>num;ll index1=(lower_bound(sum,sum+MAX,num)-sum)-1;num-=sum[index1];ll index2=(lower_bound(dp,dp+MAX,num)-dp)-1;num-=dp[index2];ll tn=index2+1;while(len(tn)>num)tn/=10;cout<<tn%10<<endl;}return 0;}



0 0