poj1019

来源:互联网 发布:java输入字符串排序 编辑:程序博客网 时间:2024/05/09 21:24

本来以为是在根据str_loc寻找要输出的数字时过于浪费时间,所以换了一种方法,将最长的串构造出来保存起来(如TLE版本2所示),但是还是超时,要哭了,做了好久了~~

 

注意:

1. 使用strlen,strcat等函数对字符串操作时,要注意'\0'

2. 不要用itoa这样的函数,他不是标准库函数,有些OJ的编译器不让过的。c有sprintf函数,c++有sstream流,都可以取代itoa函数。

如:
//把整数123 打印成一个字符串保存在s 中。
sprintf(s, "%d", 123); //产生"123"

 

sprintf还可以用来做字符串拼接

3. 用来保存以每个数字结尾的串的长度的数组location要定义成unsigned long类型(2147483647是int的最大极限)

 

 

TLE版本1

#include<stdio.h>#include<string.h>#define MAX_NUM 31268//序列长度为2147443585(大于2147483647)时最后出现的数字#define MAX_LEN 2147483647unsigned long location[MAX_NUM];//location[i]存储以数字i结尾的字符串的长度,location[0]未使用int str_loc;char make_str(int str_loc);int main(){int t;//t为test case的数目unsigned int i;//i为输入的locationint j;char ch;location[0] = 0;for(j=1; j<=MAX_NUM;j++){if(j<10){location[j] = j+location[j-1];}else if(j>=10 && j<100){//location[j] = (j-10+1)*2+9+location[j-1];location[j] = location[j-1]-location[j-2]+2+location[j-1];}else if(j>=100 && j<1000){//location[j] = (j-100+1)*3+(j%100-10+1)*2+9+location[j-1];location[j] = location[j-1]-location[j-2]+3+location[j-1];}else if(j>=1000 && j<10000){//location[j] = (j-1000+1)*4+(j%1000-100+1)*3+(j%1000%100-10+1)*2+9+location[j-1];location[j] = location[j-1]-location[j-2]+4+location[j-1];}else if(j>=10000 && j<100000){//location[j] = (j-10000+1)*5+(j%10000-1000+1)*4+(j%10000%1000-100+1)*3+(j%10000%1000%100-10+1)*2+9+location[j-1];location[j] = location[j-1]-location[j-2]+5+location[j-1];}if(location[j]>=MAX_LEN){//printf("%d-%d\n",j, location[j]);break;}//printf("%d-%d\n",j, location[j]);}scanf("%d", &t);while(t>0){scanf("%d", &i);if(i==1){printf("%d\n", 1);continue;}else if(i>1 && i<=MAX_LEN){for(j=1; j<=MAX_NUM;j++){if(i<=location[j])//找到序列结尾处的整个数字,最大为MAX_NUM{break;}}str_loc = i-location[j-1]-1;ch = make_str(str_loc);printf("%c\n",ch);}t--;}return 0;}char make_str(int str_loc){unsigned long i,tag_num;char ch;i=0;tag_num = 1;ch = '0';while(tag_num<10){ch = ch+1;if(i==str_loc)return ch;i++;tag_num++;}while(tag_num>=10 && tag_num<100){ch = tag_num/10+'0';if(i==str_loc)return ch;i++;ch = tag_num%10+'0';if(i==str_loc)return ch;i++;tag_num++;}while(tag_num>=100 && tag_num<1000){ch = tag_num/100+'0';if(i==str_loc)return ch;i++;ch = tag_num%100/10+'0';if(i==str_loc)return ch;i++;ch = tag_num%10+'0';if(i==str_loc)return ch;i++;tag_num++;}while(tag_num>=1000 && tag_num<10000){ch = tag_num/1000+'0';if(i==str_loc)return ch;i++;ch = tag_num%1000/100+'0';if(i==str_loc)return ch;i++;ch = tag_num%1000%100/10+'0';if(i==str_loc)return ch;i++;ch = tag_num%1000%100%10+'0';if(i==str_loc)return ch;i++;tag_num++;}while(tag_num>=10000){ch = tag_num/10000+'0';if(i==str_loc)return ch;i++;ch = tag_num%10000/1000+'0';if(i==str_loc)return ch;i++;ch = tag_num%10000%1000/100+'0';if(i==str_loc)return ch;i++;ch = tag_num%10000%1000%100/10+'0';if(i==str_loc)return ch;i++;ch = tag_num%10000%1000%100%10+'0';if(i==str_loc)return ch;i++;tag_num++;}}

TLE版本2:

#include<stdio.h>#include<malloc.h>#include<string.h>#define MAX_NUM 31268//序列长度为2147443585(大于2147483647)时最后出现的数字#define MAX_LEN 2147483647#define STR_LEN 145234//串123456789101112131415...312663126731268的长度(145234)unsigned long location[MAX_NUM+1];//location[i]存储以数字i结尾的字符串的长度,location[0]未使用int str_loc;char str[STR_LEN+1];//保存串123456789101112131415...312663126731268void make_str();//构造字符串123456789101112131415...312663126731268int main(){ int t;//t为test case的数目 unsigned long i=0,last_j;//i为输入的location int j; char ch; //FILE *fp; location[0] = 0; for(j=1; j<=MAX_NUM;j++) {  if(j<10)  {   location[j] = j+location[j-1];  }  else if(j>=10 && j<100)  {   location[j] = location[j-1]-location[j-2]+2+location[j-1];  }  else if(j>=100 && j<1000)  {   location[j] = location[j-1]-location[j-2]+3+location[j-1];  }  else if(j>=1000 && j<10000)  {   location[j] = location[j-1]-location[j-2]+4+location[j-1];  }  else if(j>=10000 && j<100000)  {   location[j] = location[j-1]-location[j-2]+5+location[j-1];  }  if(location[j]>=MAX_LEN)  {   break;  } }  str[0] = '\0'; make_str(); //printf("%s",str); scanf("%d", &t); while(t>0) {  last_j = j;  scanf("%d", &i);  if(i>location[last_j])//如果i比上次的location[last_j]还大,则直接从last_j查找,不用再从1查找   j = last_j;  else   j=1;  while(j<=MAX_NUM && i>location[j])//找到序列结尾处的整个数字,最大为MAX_NUM  {   j++;  }  str_loc = i-location[j-1]-1;  printf("%c\n",str[str_loc]);  t--; } return 0;}void make_str(){ int i,tag_num; int len; i=0; tag_num = 1; while(tag_num<=MAX_NUM) {  len = strlen(str);  sprintf(str+len, "%d", tag_num);  tag_num++; }}

 
 
AC的版本(需要数学功底)
参考:http://www.joansky.com/poj-1019-number-sequence-c.html
 
#include<stdio.h>#include<malloc.h>#include<string.h>#include<math.h>#define MAX_NUM 31268//序列长度为2147443585(大于2147483647)时最后出现的数字#define MAX_LEN 2147483647#define STR_LEN 145234//串123456789101112131415...312663126731268的长度(145234)unsigned long location[MAX_NUM+1];//location[i]存储以数字i结尾的字符串的长度,location[0]未使用int str_loc;char str[STR_LEN+1];//保存串123456789101112131415...312663126731268void make_str();//构造字符串123456789101112131415...312663126731268int main(){int t;//t为test case的数目unsigned long i=0,last_j;//i为输入的locationint j,k;int length;
location[0] = 0;for(j=1; j<=MAX_NUM;j++){if(j<10){location[j] = j+location[j-1];}else if(j>=10 && j<100){location[j] = location[j-1]-location[j-2]+2+location[j-1];}else if(j>=100 && j<1000){location[j] = location[j-1]-location[j-2]+3+location[j-1];}else if(j>=1000 && j<10000){location[j] = location[j-1]-location[j-2]+4+location[j-1];}else if(j>=10000 && j<100000){location[j] = location[j-1]-location[j-2]+5+location[j-1];}if(location[j]>=MAX_LEN){break;}}str[0] = '\0';
scanf("%d", &t);j=1;while(t>0){last_j = j;scanf("%d", &i);if(i>location[last_j])//如果i比上次的location[last_j]还大,则直接从last_j查找,不用再从1查找j = last_j;elsej=1;while(j<=MAX_NUM && i>location[j])//找到序列结尾处的整个数字,最大为MAX_NUM{j++;}str_loc = i-location[j-1]; /*找出该位置的数字,length:num指向的数字的最后一位的下标*/length = 0;for(k=1;str_loc>length;++k){length+=(int)(log10((double)k))+1;} /*找出num在该数字上的哪个位,去除所求位后面的数字然后取余*/printf("%u\n", (k-1)/(int)(pow((double)10,length-str_loc))%10);t--;}return 0;}
	
				
		
原创粉丝点击