回 帖 发 新 帖 刷新版面

主题:编程计算从1到2008080808之间的整数有多少个含有数字7。

这是金山的笔试题,用蛮力法是做不出来的(等死你),我用数学方法推出一个公式,其时间效率属于deta(n的平方) ,n为数字的最高位数位数,这里是10的平方,即100,请大家思考一下还有没有更高的算法呢?

回复列表 (共17个回复)

11 楼

#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 楼

编程计算从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 楼


昨天的解法是答案是错的。正确的方法是:
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 楼

看错题目了

15 楼

16 楼

使用了一种比较笨的方法,从高位开始,每位取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 楼

我想可以设计一个数据结构用来表示数据的最大值和一,当每个位的数字大于7的时候,其前一位就实现加一操作,直到各个数位的表示的真实的实际数学值的时候不大于20080080808,也可以不一定从一开始,这样同样实用!编写应该比较简单,调试通过就行。

我来回复

您尚未登录,请登录后再回复。点此登录或注册