主题:编程计算从1到2008080808之间的整数有多少个含有数字7。
lxslove
[专家分:190] 发布于 2008-06-16 11:58:00
这是金山的笔试题,用蛮力法是做不出来的(等死你),我用数学方法推出一个公式,其时间效率属于deta(n的平方) ,n为数字的最高位数位数,这里是10的平方,即100,请大家思考一下还有没有更高的算法呢?
回复列表 (共17个回复)
11 楼
dtdlut [专家分:0] 发布于 2008-09-19 21:56:00
#include<iostream.h>
int n=2008080808;
int main()
{
int num=0;
int a=0;
for(int i=0;i<=n;i++)
{
a=i;
while(a>0)
{
if(a%10==7)
{
num++;
break;
}
a=a/10;
}
}
cout << num << endl;
return 0;
}
有点慢,呵呵。没等到结果出来。。。。。。
12 楼
xjwxwy [专家分:0] 发布于 2008-10-18 19:50:00
编程计算从1到2008080808之间的整数有多少个含有数字7。
编程计算可得:
0..9 0..7 8..9
1 = 1 + 0
0..99 0..79 80..99
20 = 18 + 2
0..999 0..799 800..999
300 = 260 + 40
4000=3400+600
50000=42000+8000
600000=500000+100000
0..9999999 0..7999999 8000000..9999999
7000000 = 5800000 + 1200000
按照以上规律得到下面两列:
80000000=66000000+14000000
900000000=740000000+160000000
答案:900000000*2+5800000+42000+260+1=1805842261
13 楼
xjwxwy [专家分:0] 发布于 2008-10-19 09:36:00
昨天的解法是答案是错的。正确的方法是:
program HowManySevens;
type
abyte=array[0..0]of byte;
pbyte=^abyte;
var
ArrSum,Arr7,Arr8:array[1..9]of longint;
tf:text;
function _inc(p:pbyte;n:word):boolean;assembler;
asm
les di,[bp+6]
mov al,es:[di]
inc al
cmp al,0Ah
jl @@1
mov cx,[bp+4]
dec cx
cmp cx,00h
jz @@3
mov al,00h
mov es:[di],al
inc di
stc
@@4:
mov al,es:[di]
adc al,00h
cmp al,0Ah
jl @@1
mov al,00h
mov es:[di],al
inc di
stc
loop @@4
@@5: jc @@3
@@1: mov es:[di],al
mov al,01h
jmp @@2
@@3: mov al,00h
@@2:
end;
procedure HowManySeven(n:word);
var
i:word;
s7,s8:longint;
p:pbyte;
flag:boolean;
sts,st7,st8:string;
begin
GetMem(p,sizeof(abyte)*n);
s7:=0;s8:=0;
for i:=n-1 downto 0 do p^[i]:=0;
repeat
for i:=n-1 downto 0 do
if p^[i]=7 then
begin
if p^[n-1]<8 then inc(s7)
else inc(s8);
break;
end;
until not _inc(p,n);
Arr7[n]:=s7;Arr8[n]:=s8;ArrSum[n]:=s7+s8;
sts:='[0..';
for i:=1 to n do sts:=sts+'9';sts:=sts+']';
st7:='[0..7';
for i:=1 to n-1 do st7:=st7+'9';st7:=st7+']';
st8:='[8';
for i:=1 to n-1 do st8:=st8+'0';
st8:=st8+'..';
for i:=1 to n do st8:=st8+'9';st8:=st8+']';
writeln(sts,s7+s8,'=',st7,s7,'+',st8,s8);
writeln(tf,sts,s7+s8,'=',st7,s7,'+',st8,s8);
FreeMem(p,sizeof(abyte)*n);
end;
var
i,n:word;
Answer,k:longint;
p:pbyte;
begin
assign(tf,'Ans.txt');
rewrite(tf);
for i:=1 to 9 do
HowManySeven(i);
Answer:=ArrSum[9]*2+Arr7[7]+Arr7[5]+Arr7[3]+Arr7[1];
writeln(tf,'Answer=',Arrsum[9],'*2+',Arr7[7],'+',
Arr7[5],'+',Arr7[3],'+',Arr7[1]);
writeln('Answer=',Answer);
writeln(tf,'Answer=',Answer);
close(tf);
end.
答案放在ans.txt文件中
[0..9]1=[0..7]1+[8..9]0
[0..99]19=[0..79]17+[80..99]2
[0..999]271=[0..799]233+[800..999]38
[0..9999]3439=[0..7999]2897+[8000..9999]542
[0..99999]40951=[0..79999]34073+[80000..99999]6878
[0..999999]468559=[0..799999]386657+[800000..999999]81902
[0..9999999]5217031=[0..7999999]4279913+[8000000..9999999]937118
[0..99999999]56953279=[0..79999999]46519217+[80000000..99999999]10434062
[0..999999999]612579511=[0..799999999]498672953+[800000000..999999999]113906558
Answer=612579511*2+4279913+34073+233+1
Answer=1229473242
14 楼
boxertony [专家分:23030] 发布于 2008-10-23 14:21:00
看错题目了
15 楼
boxertony [专家分:23030] 发布于 2008-10-23 14:24:00
唉
16 楼
estfania [专家分:0] 发布于 2008-11-03 15:59:00
使用了一种比较笨的方法,从高位开始,每位取search值
假设每一位为当前值,则相应的所有可能值为:前半部分中所有不含该值数*后半部分所有可能的值
代码比较粗糙,还有待改进
#define MAX_LENGTH (32)
int get_numbers(int input,int search)
{
int location[MAX_LENGTH];
int index;
int x;
int low;
int i,k;
unsigned int residule_front,residule_end;
int numbers,num_part_front,num_part_end;
if(search > 9)
return -1;
memset(location,0,sizeof(int)*MAX_LENGTH);
index = 0;
x = input;
while(x)
{
if(x >= 10)
{
low = x%10;
location[index++] = low;
x = x/10;
}
else
{
location[index++] = x;
break;
}
}
printf("at line:%d,index:%d\n",__LINE__,index);
numbers = 0;
/*处理最高位的情况*/
if(location[index-1] > search)
numbers = pow(10,index-1);
else if(location[index-1] == search)
{
numbers = 0;
k = index - 2;
while(k >= 0)
{
numbers *= 10;
numbers += location[k];
k--;
}
numbers++;
/*为搜索位的数据减1*/
}
else
numbers = 0;
printf("at line:%d,numbers:%d\n",__LINE__,numbers);
for(i=index-2;i>=0;i--)
{
/*得到该位数据前面的值*/
k = index - 1;
residule_front = 0;
while(k>i)
{
residule_front *= 10;
residule_front += location[k];
k--;
}
num_part_end = pow(10,i);
#define FORALL
#ifdef FORALL
if(location[i] == search && location[i+1] != search && location[i+1] != 0)
{
k = i - 1;
residule_end = 0;
while(k >= 0)
{
residule_end *= 10;
residule_end += location[k];
k--;
}
printf("residule_end:%d\n",residule_end);
num_part_front = (residule_front+1) - get_numbers(residule_front,search);
numbers += num_part_end*num_part_front;
printf("numbers:%d\n",numbers);
numbers -= (num_part_end - residule_end - 1);
printf("num_part_end:%d\n",num_part_end);
}
else
{
#endif
if(location[i] < search)
residule_front -= 1;
num_part_front = (residule_front+1) - get_numbers(residule_front,search);
numbers += num_part_end*num_part_front;
printf("at line:%d,numbers:%d\n",__LINE__,numbers);
#ifdef FORALL
}
#endif
}
return numbers;
}
17 楼
34353520 [专家分:60] 发布于 2008-11-05 14:56:00
我想可以设计一个数据结构用来表示数据的最大值和一,当每个位的数字大于7的时候,其前一位就实现加一操作,直到各个数位的表示的真实的实际数学值的时候不大于20080080808,也可以不一定从一开始,这样同样实用!编写应该比较简单,调试通过就行。
我来回复