[C/C++]一个关于数字的问题

Lynn_Ran 2008-06-26 12:39:27
问题是这样的:
求出1到2008080808中含有7的数字的个数

例如:
7 17 27
...全文
218 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
xjwxwy 2008-10-19
  • 打赏
  • 举报
回复
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
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
Lynn_Ran 2008-06-28
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 deng2000 的回复:]
简单的分析可避免复杂的循环计算.
让我们先找出1到2008080808之间所有不含数字7的数的个数。
考虑把1到2008080808之间的所有数字按顺序排列如下(在数字前面补零以便对齐):

0000000001
0000000002
...
2008080807
2008080808

想象把所有含有数字7的数从上面的排列中抽取掉,再把剩下的数按原来的顺序排列如下:

0000000001
0000000002
...
2008080806
2008080808

我们需要找出上面的排列一…
[/Quote]

果然强汉……领教了
jinjunweiruan 2008-06-28
  • 打赏
  • 举报
回复
菜鸟想的:
能否让电脑自己生成200802...这个大数字,并把他列出来。
再用CHAR,强制,找出有7的数字??
不知道这样能否可以¥%%%
solew 2008-06-27
  • 打赏
  • 举报
回复
是否可以看看我设计的求值代码。

/*简单的验证函数(未做优化),该函数在数字很低时执行还快,但是数字大时就让人难以忍受,但是该

code可以对code的结果进行校验,该校验的思想是:对任意数字,从0到该数值循环,每取一个数字,对其的

每个位进行判断(从低位到高位,取模),如果有7,则计数,退出,验下一数。
*/
int check_count(u_long input)
{
u_long ret = 0,i=0,k=0;
for(i=1;i<=input;i++) //从1开始校验。
{
k = i;
while(k)
{
/*可考虑做些优化,比如k是尾数时,可以每次i+=10,k不是尾数时,ret和i可以

一次加上10...0(0的位数由k的位数决定)。
*/
if((k%10)==7)//该位为7?为7,则计数,退出,验下一个数。
{
ret++;
break;
}
k /=10;//取下一位
}
}
cout<<"1到"<<input<<"中含7的数字有"<<ret<<"个。"<<endl;
return ret;
}
//计算一个数字number 的k次方。
int ncount(int number,int k)
{
int ret = 1;
int i=k;

while(i--)
{
ret *= number;
}
cout<<"ncount,number="<<number<<",k="<<k<<",ret="<<ret<<endl;
return ret;
}
/*/计算10^n中所包含的7的数字。
输入位数Ni
n 数值 计算式
0 1 0
1 10 1
2 100 10+9(10*7-+(10-1)*-7)
3 1000 10*10+10*9+9*9(10*10*7--+(10-1)*9*-7-+(10-1)*

(10-1)*--7)
4 10000 10*10*10+10*10*9+10*9*9+9*9*9
....
n 100.....0 10^(n-1)+10^(n-2)*9+....+10*9^(n-2)+9^

(n-1)
*/
int count_n(int n)
{
int k,sum = 0;

if(n==0)
return 0;

for(k = 0;k < n;k++)
{
sum += ncount(9,k)*ncount(10,n-1-k);
}
cout<<"cout it,n="<<n<<",sum="<<sum<<endl;

return sum;
}
/*
输入任意一个数字,number*10*10*....*10(k个10的乘积)
求其中所包含7的数字的字数。
设0-1000中含7的字数为N3个。
...
则0-6000中含7的字数应该为6*N3
则0-7***中含7的字数应该为7*N3+***
则0-8000中含7的字数应该为(8-1)*N3+1000,扣除了7开头的那部分,所以只能用8-1
则0-9000中含7的字数应该为(9-1)*N3+1000,扣除了7开头的那部分,所以只能用9-1
则如下数字0-68798347中含7的个数应该为:
((6)*N7)+((8-1)*N6+10^6)+(7*N5+98347)+((9-1)*N4+10^4)+((8-1)*N3+10^3)+(3*N2)+(4*N1)+

(7*N0)
*/

int sum_count()
{
u_long origin,input,rev_input = 0;
int sum = 0;
int n = 0,k=0,x9=1,x10=1;
cout<<"please input the number:"<<endl;
cin>>origin;
input = origin;
cout<<"input="<<input<<endl;

check_count(input);

while(input)
{
rev_input =rev_input*10+input%10;
n++;
//sum += get_count(input%10,n++);
input /= 10;
}

cout<<"byte="<<n<<endl;
while(rev_input)
{
int number = 0;
number= rev_input%10; //get the high number.
n--;

if(!number)
sum += 0;
if(number > 7)
sum += ncount(10, n)+(number-1)*count_n(n);//except the 7*
else if(number < 7)
sum += number*count_n(n);
if(number == 7)
{
//include 700...0-7******+0-699...9
sum += origin%ncount(10,n)+ 1+number*count_n(n) ;
break;
}

rev_input /= 10;

}

cout<<"result="<<sum<<endl;

return sum;

}
deng2000 2008-06-27
  • 打赏
  • 举报
回复
简单的分析可避免复杂的循环计算.
让我们先找出1到2008080808之间所有不含数字7的数的个数。
考虑把1到2008080808之间的所有数字按顺序排列如下(在数字前面补零以便对齐):

0000000001
0000000002
...
2008080807
2008080808

想象把所有含有数字7的数从上面的排列中抽取掉,再把剩下的数按原来的顺序排列如下:

0000000001
0000000002
...
2008080806
2008080808

我们需要找出上面的排列一共有多少个数. 初看好像没什么规律,但如果把它们想象成
"九进制"数就豁然开朗了.上面的排列实际上是九进制数中从1到2008080808的按顺序
排列! 当然,这个九进制有点特殊:它的字母表是{0,1,2,3,4,5,6,8,9},而不是通常的
{0,1,2,3,4,5,6,7,8}, 我们可作一个简单的映射 8-->7, 9-->8, 把它变成通常意义
下的九进制数排列:

0000000001
0000000002
...
2007070706
2007070707

因此,此排列中的数字个数为
2*9^9 + 7*9^6 + 7*9^4 + 7*9^2 + 7 = 778607566
此即1到2008080808之间所有不含数字7的数的个数. 故本问题的答案是
2008080808 - 778607566 = 1229473242
solew 2008-06-27
  • 打赏
  • 举报
回复
是否可以看看我设计的求值代码。(不知道怎么换行,还加了些注释,希望有助于大家理解,可以把之前的那个回复去掉了。)

/*简单的验证函数(未做优化),该函数在数字很低时执行还快,但是数字大时就让人难以忍受,但是该

code可以对code的结果进行校验,该校验的思想是:对任意数字,从0到该数值循环,每取一个数字,对其的

每个位进行判断(从低位到高位,取模),如果有7,则计数,退出,验下一数。
*/
int check_count(u_long input)
{
u_long ret = 0,i=0,k=0;
for(i=1;i <=input;i++) //从1开始校验。
{
k = i;
while(k)
{
/*可考虑做些优化,比如k是尾数时,可以每次i+=10,k不是尾数时,ret和i可以
一次加上10...0(0的位数由k的位数决定)。 */
if((k%10)==7)//该位为7?为7,则计数,退出,验下一个数。
{
ret++;
break;
}
k /=10;//取下一位
}
}
cout < <"1到" < <input < <"中含7的数字有" < <ret < <"个。" < <endl;
return ret;
}
//计算一个数字number 的k次方。
int ncount(int number,int k)
{
int ret = 1;
int i=k;

while(i--)
{
ret *= number;
}
cout < <"ncount,number=" < <number < <",k=" < <k < <",ret=" < <ret < <endl;
return ret;
}
/*计算10^n中所包含的7的数字。
输入位数Ni
n 数值 计算式
0 1 0
1 10 1
2 100 10+9(10*7-+(10-1)*-7)
3 1000 10*10+10*9+9*9(10*10*7--+(10-1)*9*-7-+(10-1)*(10-1)*--7)
4 10000 10*10*10+10*10*9+10*9*9+9*9*9
....
n 100.....0 10^(n-1)+10^(n-2)*9+....+10*9^(n-2)+9^(n-1)
*/
int count_n(int n)
{
int k,sum = 0;

if(n==0)
return 0;

for(k = 0;k < n;k++)
{
sum += ncount(9,k)*ncount(10,n-1-k);
}
cout < <"cout it,n=" < <n < <",sum=" < <sum < <endl;

return sum;
}
/*
输入任意一个数字,number*10*10*....*10(k个10的乘积)
求其中所包含7的数字的字数。
设0-1000中含7的字数为N3个。
...
则0-6000中含7的字数应该为6*N3
则0-7***中含7的字数应该为7*N3+***
则0-8000中含7的字数应该为(8-1)*N3+1000,扣除了7开头的那部分,所以只能用8-1
则0-9000中含7的字数应该为(9-1)*N3+1000,扣除了7开头的那部分,所以只能用9-1
则如下数字0-68798347中含7的个数应该为:
((6)*N7)+((8-1)*N6+10^6)+(7*N5+98347)+((9-1)*N4+10^4)+((8-1)*N3+10^3)+(3*N2)+(4*N1)+(7*N0)
*/

int sum_count()
{
u_long origin,input,rev_input = 0;
int sum = 0;
int n = 0,k=0,x9=1,x10=1;
cout < <"please input the number:" < <endl;
cin>>origin;
input = origin;
cout < <"input=" < <input < <endl;

check_count(input);

//将数字逆序,以逐位判断
while(input)
{
rev_input =rev_input*10+input%10;
n++;
//sum += get_count(input%10,n++);
input /= 10;
}

cout < <"byte=" < <n < <endl;
while(rev_input)
{
int number = 0;
number= rev_input%10; //从最高位开始判断和统计
n--;

if(!number)//当前最高位为0,则加0。
sum += 0;
if(number > 7)//当前最高位大于7
sum += ncount(10, n)+(number-1)*count_n(n);//except the 7*
else if(number < 7)//当前最高位小于7
sum += number*count_n(n);
if(number == 7) //当前最高位正好等于7,即从70...0--7*****这些数全部都含7
{
//include 700...0-7******+0-699...9
sum += origin%ncount(10,n)+ 1+number*count_n(n) ;
break;
}
rev_input /= 10; //取下一位数。
}
cout < <"result=" < <sum < <endl;
return sum;
}
Lynn_Ran 2008-06-27
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 wangboqun99 的回复:]
上面的是算出1到800以内的含有7的数字的个数,依次内推啊
[/Quote]

你可以试试到2008080808 你一时半会出不来结果了

期待baihacker 给点高见……
wangboqun99 2008-06-27
  • 打赏
  • 举报
回复
上面的是算出1到800以内的含有7的数字的个数,依次内推啊
wangboqun99 2008-06-27
  • 打赏
  • 举报
回复
#include "iostream.h"
void main()
{
long count=0;
long i,c,d;
for(i=1;i<800;i++)
{
d=i;
while (d!=0)
{
c=d%10;
if (c==7)
{
count++;
break;
}
d=d/10;
}

}
cout<<count<<endl;
}
ooily 2008-06-26
  • 打赏
  • 举报
回复
去找找以前求含’1‘的帖子吧,懒得找了
Lynn_Ran 2008-06-26
  • 打赏
  • 举报
回复

#include <iostream>

using namespace std;



const int MAX = 2008080808;

const int IT = 7;



template<int n, int curr, int last, int base, int weight>

class A

{

enum{it = n/base%10};

public:

enum{result = A<n, (it-(it>IT))* weight+((it<IT)?curr:(it==IT?last:base+curr)), last+base*it, base*10, (weight?weight*9+base:1)> :: result};

};



template<int n, int curr, int base, int weight>

class A<n, curr, n, base, weight>

{

public:

enum {result = curr};

};



int main(int argc, char* argv[])

{

cout << A<MAX+1, 0, 0, 1, 0>:: result << endl;

return 0;

}


baihacker 这个……代码能给点注释么……看的我迷茫死了……
Lynn_Ran 2008-06-26
  • 打赏
  • 举报
回复
那个帖子好像不见了……
谁还记得……?
pengzhixi 2008-06-26
  • 打赏
  • 举报
回复
前段时间都有人讨论过了啊,好象有个牛人提供了一个公式吧。好象用一个9进制和8进制就解决了
MagiSu 2008-06-26
  • 打赏
  • 举报
回复
唉,这个题目baihacker已经做过了,我看是做得最漂亮的。

题目思想很简单。

从0-9只有1个7,然后0-100中以10为步长每一段都只有一个7,除了70,因此如果是小于70一种算法,大于70另一种算法。
然后类推即可。速度奇快无比。
K行天下 2008-06-26
  • 打赏
  • 举报
回复

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
int n = 2*(pow(10.0,9) - pow(9.0,9)) + 7*(pow(10.0,6) - pow(9.0,6) +
pow(10.0,4) - pow(9.0,4) + 19) + 1000000 + 10000 + 100 +1;
cout<<n<<endl;
system("PAUSE");
return 0;
}

//解释原因: 分为几段
0-999999999 1000000000 - 1999999999 // 这2段的含7个数是2*(pow(10.0,9) - pow(9.0,9))
以下的继续按此分段


以前有一个帖子上有,不记得在哪里了
tmxk5028 2008-06-26
  • 打赏
  • 举报
回复
这应是一个数学的排列组合 问题!?思考......
Lynn_Ran 2008-06-26
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 songqiangqiang 的回复:]
是不是从1到2008080808遍历

for(data=1;data <2008080808;data++)
{
while(data!=0)
{
余数=data%10;
除数=data/10;
if(余数==7){输出;break;}
data=除数;


}
}
不知道有没有更好的办法。。。
[/Quote]

我写出来试了 没有三五分钟出不了结果……
Lynn_Ran 2008-06-26
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 lc315439849 的回复:]
int j = 0;
for( int i = 7; i < 2008080808; i += 10 )
{
j++;
}
cout < < j < < endl;
[/Quote]

你理解有问题啊 70-79也算含有7
lc315439849 2008-06-26
  • 打赏
  • 举报
回复
int j = 0;
for( int i = 7; i < 2008080808; i += 10 )
{
j++;
}
cout<< j << endl;
songqiangqiang 2008-06-26
  • 打赏
  • 举报
回复
应该有因为要是7不在个位上就表示后面的若干位均有1 比如70~79,700~799而下一次搜索从80,800开始就好了
所以上面的程序可以改一下
m=1;
for(data=1;data <2008080808;data+=m)
{
j=1;
while(data!=0)
{
余数=data%10;
除数=data/10;
if(余数==7)
{
输出data~data+j-1;
m=j;
break;
}
data=除数;
j*=10;

}
}
加载更多回复(3)

64,641

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧