题意:给你一个串数字
1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 123456789101112······k
很容易发现规律,T组测试数据,每组输入一个n,问这个序列的n位置是哪个数字?
思路:两种方法:①模拟 ②数学方法
方法一:模拟,如果直接模拟这个序列太长,放不下。我们可以发现前面这些序列是长什么样子对答案没有影响,他们的长度才有用,所以我们直接模拟123456789101112······k这个串用s保存,用一个变量len保存当前长度,每增加一位就让len+s.size(),然后让n-len表示答案是在当前串的n-len位,当n小于等于s.size()时结束。
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int MAXN = 100005;
int main()
{
int T; scanf("%d", &T);
while (T--)
{
int n; scanf("%d", &n);
string s; char num[105];
int k = 1, len = 0;
while (n > s.size())
{
sprintf(num, "%d", k);
s += num;
len += strlen(num);
n -= len;
k++;
}
if (n != 0) printf("%c\n", s[n-1]);
else printf("%c\n", s[s.size()-1]);
}
return 0;
}
/*
2
8
3
*/
方法二:数学方法。大神们真是厉害!!!
模拟分组,把1看做第1组,12看做第2组,123看做第3组,1234看做第4组……那么第i组就是存放数字序列为 [1,i]的正整数,但第i组的长度不一定是i
先打表,然后找到对应的组,然后在找到对应位置的数字,算出答案。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN = 31269;
typedef long long ll;
ll a[MAXN]; //a[i] 表示第i组数字序列的长度
ll s[MAXN]; //s[i] 表示前i组数字序列的长度
/*打表,预先获取第2147483647个位的序列分组情况*/
void play_table()
{
a[0] = s[0] = 0;
for(int i = 1; i < MAXN; i++)
{
a[i] = a[i-1] + (int)log10((double)i) + 1;
s[i] = s[i-1] + a[i];
}
}
int main()
{
play_table();
int T; scanf("%d", &T);
while(T--)
{
int n; scanf("%d", &n);
int i = 1;
while(s[i] < n) i++;
int pos = n - s[i-1];
i = 1;
while (a[i] < pos) i++;
int len = a[i];
int ans = i/(int)pow((double)10, len - pos)%10;
printf("%d\n", ans);
}
return 0;
}
/*
2
8
3
*/