pku1019

看到位数最大为2147483647,考虑寻找规律进行打表。

1~9:每次增加一位,那么占的总位数为45

10~99:每次增加二位,那么占的总位数为9000

100~999:每次增加三位,那么占的总位数为1387800

1000~9999:每次增加四位,那么占的总位数为18979200

此时总的位数为45+9000+1387800+18979200 = 20376045 < 2147483647

10000~99999:每次增加5位,那么占的总位数为22009140000 比 2147483647还要多一位。

所以我们要找规律,增加的位数规律为log10(i)+1。可以用数组存储起来,先来用程序算下总共需要多大的数组:

#include<math.h>
#include<iostream>
using namespace std;
unsigned int a[100000];
unsigned int sum[100000];
int main(){
	a[1] = 1;
	sum[1] = 1;
	int i;
	for(i = 2;i<100000;i++){
		a[i] = a[i-1]+(int)log10((double)i)+1;
		sum[i] = sum[i-1]+a[i];
		if(sum[i] > 2147483647)
			break;
	}
	cout<<i<<endl;
	return 0;
}

输出为31268.

那么有了数组如何计算所在位的数字呢,先确定位数是在哪个组中(一个序列为一组,比如12为一组,123456789也为一组),然后算出在这个组中的位移偏量。从所在组的第一位开始,直到算出所在数字,然后再求其位数是什么,代码如下:

#include<math.h>
#include<iostream>
using namespace std;
const int size = 31269;
unsigned int a[size];
unsigned int sum[size];
int main(){
	//初始化
	a[1] = sum[1] =1;
	for(int i =2;i<size;++i){
		a[i] = a[i-1]+(int)log10((double)i)+1;
		sum[i] = sum[i-1]+a[i];
	}
	int m,n;
	cin>>n;
	while(n != 0){
		cin>>m;
		int i =1;
		//算出在哪个组中
		while(m >sum[i])
			i++;
		//位移偏量
		int len = m-sum[i-1];
		int pos = 0;
		//找到所在组中的数字
		for(i =1; pos<len;i++)
			pos = a[i];
		//之前i多了一位是pos>len,所以要减去,这里是已知数字,求
		//所在位数,比如1234,求3,那么就是(1234/10)%10
		int result = (i-1)/(int)pow((double)10,(pos-len))%10;
		cout<<result<<endl;
		n--;
	}
}

打表果真够快,速度是0ms



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值