nyist 413 && poj 1019 Number Sequence

题目链接:   nyist       poj

Description

A single positive integer i is given. Write a program to find the digit located in the position i in the sequence of number groups S1S2...Sk. Each group Sk consists of a sequence of positive integer numbers ranging from 1 to k, written one after another.
For example, the first 80 digits of the sequence are as follows:
112123123412345123456123456712345678123456789123456789101234567891011

题意:给出一串那样的数字,很有规律的,总共有2147483647位,然后问你第 n 位上的数字是多少。一开始我理解错题意了,以为是问第 n 位的数是多少,WA了2次之后才发觉超过10以后的数字都不止1位了...悲剧

一开始做的复杂了,后来才发现数字的位数可以用 log10((double)i) + 1 这个公式求出来,这样逐步求精就可以慢慢地求出结果了。

1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 ......
按上面数列所示,我们把数列分为N段,第N-1段总是第N段的一个子集! 我们首先计算出最长的最大的最后一个段,假设第2147483647位处在第N段,我们则把这个第N段保存下来!

具体做法是用两个数组保存上面的数据,b[ ] 数组保存的是每段数的位数,b[i] 表示第i段位数,a[ ] 数组表示前面所有段的位数,a[i]表示前i段一共有多少位。解题的时候两次二分就可以了。比如查找第N位,先通过数组a[ ] 查找第N位在第几段,算出第几段的第几位,然后通过b[]数组确定第几位是多少。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
unsigned int a[32000],b[32000];
int main()
{
	unsigned int n,m,i,j,k;
	for(i=1,k=0;i<31270;i++)
	{
		b[i]=b[i-1]+(int)log10(double(i))+1;
		a[i]=a[i-1]+b[i];
	}
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d",&m);
		unsigned int mm=m-a[lower_bound(a,a+31270,m)-a-1];
		unsigned int *p=lower_bound(b,b+31270,mm);
		cout<<(p-b)/(int)pow((double)10,(int)(*p-mm))%10<<endl;;
	}
}        

 


还有一种方法是:a[]数组存储的信息不变,b[]数组存储的是序列12345678910111213......等各位位数对应数组数组的值,即b[1]=1, b[2]=2, b[3]=3, b[4]=4, b[5]=5, b[6]=6, b[7]=7, b[8]=8, b[9]=9,   b[10]=1,b[11]=0,    b[12]=1,b[13]=1,   b[14]=1,b[15]=1,   b[16]=1,b[17]=2,   b[18]=1,b[19]=3 .....等,由a数组查询计算出某段的第几位时(比如 i),直接对应输出就可以(b[i]); b数组一个循环就可;

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
long long  a[32000],b[200100];
int myitoa(int n,char *s) //itoa不是标准库函数,自己实现个
{ 
	return (n/10&&(*(s+myitoa(n/10,s)+1)=n%10+'0'))?(myitoa(n/10,s)+1):!(*s=n+'0');//这个函数功能就是把数字n转换成字符串而已,具体实现很简单, 不用像我这样写这么长一段话,只是当时好玩才这样写;
}
void ac()
{
	long long k=0,i,j;
	for(i=1;i<31500;i++)
	{
		k=k+(int)(log10(double(i)))+1;
		a[i]=a[i-1]+k;
	}
	char c[10];
	for(i=1,k=1;i<32000;i++)
	{
		memset(c,0,sizeof(c));
		myitoa(i,c);
		for(j=0;j<strlen(c);j++)
			b[k++]=c[j]-'0';
	}
}
int main()
{
	long long n,m;
	ac();
	scanf("%lld",&n);
	while(n--)
	{
		scanf("%lld",&m);
		long long *q=lower_bound(a,a+31400,m);
		cout<<b[m-a[q-a-1]]<<endl;
	}
	return 0;
}        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是51单片机控制的12864液晶显示系统编程实现所需的代码: ``` #include <reg51.h> #include <intrins.h> #define LCD_DB P0 sbit LCD_RS = P2^6; // RS信号 sbit LCD_RW = P2^5; // RW信号 sbit LCD_E = P2^7; // E信号 sbit LCD_CS1 = P2^0; // CS1信号 sbit LCD_CS2 = P2^1; // CS2信号 void delay(unsigned int i) // 延时函数 { while(i--); } void write_com(unsigned char com) // 写命令函数 { LCD_RS = 0; LCD_RW = 0; LCD_DB = com; LCD_E = 1; _nop_(); _nop_(); LCD_E = 0; } void write_data(unsigned char dat) // 写数据函数 { LCD_RS = 1; LCD_RW = 0; LCD_DB = dat; LCD_E = 1; _nop_(); _nop_(); LCD_E = 0; } void init_lcd() // 初始化函数 { write_com(0xc0); // 设置显示模式 write_com(0x3f); // 允许显示 write_com(0x40); // 设置起始地址 write_com(0xb8); // 设置页地址 write_com(0xc0); // 设置列地址 write_com(0x40); // 设置起始地址 write_com(0xb8); // 设置页地址 write_com(0xc0); // 设置列地址 } void display_string(unsigned char x, unsigned char y, unsigned char *s) // 显示字符串函数 { unsigned char i; if(y == 0) // 第一行居中显示“南阳理工学院” { write_com(0xb8 + x); write_com(0x40); } else if(y == 1) // 第二行居中显示“www.nyist.edu.cn” { write_com(0xb8 + x); write_com(0x48); } else if(y == 2) // 第三行居中显示“电子信息工程专业” { write_com(0xb8 + x); write_com(0x50); } else if(y == 3) // 第四行居中显示尚春芳 { write_com(0xb8 + x); write_com(0x58); } for(i = 0; s[i] != '\0'; i++) { write_data(s[i]); } } void main() { init_lcd(); // 初始化LCD display_string(18, 0, "南阳理工学院"); // 显示第一行 display_string(16, 1, "www.nyist.edu.cn"); // 显示第二行 display_string(16, 2, "电子信息工程专业"); // 显示第三行 display_string(22, 3, "尚春芳"); // 显示第四行 while(1); } ``` 以上代码实现了你提出的要求,第一行居中显示“南阳理工学院”,第二行居中显示“www.nyist.edu.cn”,第三行居中显示“电子信息工程专业”,第四行居中显示尚春芳。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值