题意
题目大意是说,有一串由如下如下规律的数字组成的字符串1121231234123451234561234567…….,给出任意一个位置,求那个位置的数字是多少。
分析
观察一下,可以把字符串分成1 12 123 1234 12345 …12345678910…,这样1到9段,每段的长度可以用n表示,从10到99段每段可以用2n-9表示、、、。这样前n段的长度可表示为0.5n*n+0.5n[1,10),n*n-8n+36[10,100),1.5n*n-106.5n+4887[100,999),2n*n-1105n+503388[1000,9999),2.5n*n-11103.5n+50488389[10000,99999)。因此先估算所求位置在哪个区间里,解一个一元二次方程,再具体求值即可。
其本质就是求等差数列的和。
代码如下:
Memory: 256K Time: 0MS Length:54LINES
#include<iostream>
#include<cmath>
using namespace std;
unsigned int Sum[5] = { 0, 45, 9045, 1395495, 189414495 };//用来判断在哪个区间
unsigned int Count[5] = { 0, 9, 189, 2889, 38889 };
int Calc(unsigned int num)
{
for (int i = 4; i > 0; --i)
{
if (num > Count[i])
{
int mod = (num - Count[i]) % (i + 1);
if (mod > 0) num = num - Count[i] + (i + 1) - mod;
else num -= Count[i];
num = num / (i + 1) + pow(10.0, i) - 1;
if (mod != 0) num /= pow(10.0, (i + 1 - mod));
return num % 10;
}
}
return num;
}
struct A_B_C
{
double a;
double b;
unsigned int c;
};
int main()
{
A_B_C abc[5];//方程参数
abc[0].a = 0.5; abc[0].b = 0.5; abc[0].c = 0;
abc[1].a = 1; abc[1].b = -8; abc[1].c = 36;
abc[2].a = 1.5; abc[2].b = -106.5; abc[2].c = 4887;
abc[3].a = 2; abc[3].b = -1105; abc[3].c = 503388;
abc[4].a = 2.5; abc[4].b = -11103.5; abc[4].c = 50488389;
unsigned int num = 0;
int count = 0;
cin >> count;
while (count--)
{
cin >> num;
for (int i = 4; i >= 0; --i)
if (num > Sum[i])
{
double tmp = sqrt(abc[i].b * abc[i].b + 4 * abc[i].a * (num - abc[i].c));
int val = (-abc[i].b + tmp) / (2 * abc[i].a);
int val2 = num - abc[i].a * val * val - abc[i].b * val - abc[i].c;
if (val2 == 0) cout << val % 10 << endl;//若刚好在前n段的最后位置
else cout << Calc(val2) << endl; //超出的再处理即可
break;
}
}
return 0;
}
1011



被折叠的 条评论
为什么被折叠?



