北大1019
2008-10-25 21:17
288 查看
题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1019
这个题目很有意思!
1,第一次WA很有趣,完全是因为想当然没审清题,错误地认为第i组有i个数字,其实不然从题目给的前80个数字就应该容易看出来,因为当数字大于9时,一个数字就产生了多个数字。
2,后来用int做,结果测试i = 2147483647(2^31-1)时,中间结果溢出产生了错误,后来改为unsigned才对
3,设第i组有N(i)个数字,那么第i+1组有N(i+1) = N(i) + Digit(i+1)个数字,利用这个式子求下标元素所在的组可以减少不少运算。否则根本运行时间太长。
耗时版
#include <iostream>
#include <cmath>
using namespace std;
int Digit(int m)
{
int t = 0;
while(m > 0)
{
++t;
m /= 10;
}
return t;
}
int main()
{
freopen("in.txt","r",stdin);
int t,i,m,n,p;
cin >> t;
unsigned k;
while(t--)
{
cin >> i;
k = 0;
for(m = 1;;++m)
{
if(m == 10000)//测试用结果耗时相当长
{
int a;
a = 10;
}
if(m == 20000)
{
int a;
a = 10;
}
if(m == 30000)
{
int a;
a = 10;
}
for(n = 1;n <= m;++n)
k += Digit(n);
if(k >= i)
break;
}
if(i == k)
{
cout << m % 10 << endl;
continue;
}
else
{
for(n = m;n >= 1;--n)
{
k -= Digit(n);
if(k <= i)
break;
}
if(i == k)
{
cout << (n-1) % 10 << endl;//这里必须是n-1才行!说明去掉n正好,就是意味着n-1的所有数都包括进来正好够!
continue;
}
else
{
++n;
p = Digit(n) - (i - k);
while(p > 0)
{
n /= 10;
--p;
}
cout << n % 10 << endl;
}
}
}
return 0;
}
正确版:
#include <iostream>
using namespace std;
int Digit(int m)
{
int t = 0;
while(m > 0)
{
++t;
m /= 10;
}
return t;
}
int main()
{
freopen("in.txt","r",stdin);
unsigned int t,i,j,k,m,n;
cin >> t;
while(t--)
{
cin >> i;
n = k = 0;
for(j = 1;;++j)
{
n = n + Digit(j);//拆开写,更能体现迭代!
k += n;
if(k >= i)
break;
}
if(k == i)
{
cout << j % 10 << endl;
continue;
}
else
{
k -= n;
for(m = 1;m <= j;++m)
{
k += Digit(m);
if(k >= i)
break;
}
if(k == i)
{
cout << m % 10 << endl;
continue;
}
else
{
k -= Digit(m);
n = Digit(m) - (i - k);
while(n != 0)
{
m /= 10;
--n;
}
cout << m % 10 << endl;
}
}
}
return 0;
}
这个题目很有意思!
1,第一次WA很有趣,完全是因为想当然没审清题,错误地认为第i组有i个数字,其实不然从题目给的前80个数字就应该容易看出来,因为当数字大于9时,一个数字就产生了多个数字。
2,后来用int做,结果测试i = 2147483647(2^31-1)时,中间结果溢出产生了错误,后来改为unsigned才对
3,设第i组有N(i)个数字,那么第i+1组有N(i+1) = N(i) + Digit(i+1)个数字,利用这个式子求下标元素所在的组可以减少不少运算。否则根本运行时间太长。
耗时版
#include <iostream>
#include <cmath>
using namespace std;
int Digit(int m)
{
int t = 0;
while(m > 0)
{
++t;
m /= 10;
}
return t;
}
int main()
{
freopen("in.txt","r",stdin);
int t,i,m,n,p;
cin >> t;
unsigned k;
while(t--)
{
cin >> i;
k = 0;
for(m = 1;;++m)
{
if(m == 10000)//测试用结果耗时相当长
{
int a;
a = 10;
}
if(m == 20000)
{
int a;
a = 10;
}
if(m == 30000)
{
int a;
a = 10;
}
for(n = 1;n <= m;++n)
k += Digit(n);
if(k >= i)
break;
}
if(i == k)
{
cout << m % 10 << endl;
continue;
}
else
{
for(n = m;n >= 1;--n)
{
k -= Digit(n);
if(k <= i)
break;
}
if(i == k)
{
cout << (n-1) % 10 << endl;//这里必须是n-1才行!说明去掉n正好,就是意味着n-1的所有数都包括进来正好够!
continue;
}
else
{
++n;
p = Digit(n) - (i - k);
while(p > 0)
{
n /= 10;
--p;
}
cout << n % 10 << endl;
}
}
}
return 0;
}
正确版:
#include <iostream>
using namespace std;
int Digit(int m)
{
int t = 0;
while(m > 0)
{
++t;
m /= 10;
}
return t;
}
int main()
{
freopen("in.txt","r",stdin);
unsigned int t,i,j,k,m,n;
cin >> t;
while(t--)
{
cin >> i;
n = k = 0;
for(j = 1;;++j)
{
n = n + Digit(j);//拆开写,更能体现迭代!
k += n;
if(k >= i)
break;
}
if(k == i)
{
cout << j % 10 << endl;
continue;
}
else
{
k -= n;
for(m = 1;m <= j;++m)
{
k += Digit(m);
if(k >= i)
break;
}
if(k == i)
{
cout << m % 10 << endl;
continue;
}
else
{
k -= Digit(m);
n = Digit(m) - (i - k);
while(n != 0)
{
m /= 10;
--n;
}
cout << m % 10 << endl;
}
}
}
return 0;
}
相关文章推荐
- 80老翁谈人生(102):从北大“三角地”谈起
- 80老翁谈人生(133):老翁发飚,痛批北大人事管理之无能
- PAT乙级 1019. 数字黑洞
- [BZOJ1019][SHOI2008]汉诺塔(动态规划)
- 80老翁谈人生(160):北大人事部下定决心,顶风违纪
- 1019 数字黑洞
- [bzoj 1019--SHOI2008]汉诺塔
- 【bzoj1019】[SHOI2008]汉诺塔
- PAT 1019. General Palindromic Number
- 80老翁谈人生(211):北大为何驱赶火星人,使其不能再发声捣乱?
- 1019
- 80老翁谈人生(227):痛批北大信访违纪派
- poj-1019-Number Sequence【思维】【规律】
- PAT(basic level) 1019 数字黑洞(20)
- 【bzoj1019】[SHOI2008]汉诺塔
- FZU1019-猫捉老鼠
- PAT 1019. 数字黑洞 (20)
- 1019. 数字黑洞 (20)
- PAT BASIC LEVEL 1019. 数字黑洞 (20)
- 1019. 数字黑洞 (20)