google的一道面世题,算法高手进来看看。

TheAres 2005-08-16 12:59:48
加精
这个题目的英文原题是:
Consider a function which, for a given whole number n, returns the number of ones required when writing out all numbers between 0 and n.

For example, f(13)=6. Notice that f(1)=1. What is the next largest n such that f(n)=n?

翻译过来大体是这样:
有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数。比如f(13)=6,现在f(1)=1,问下一个最大的f(n)=n的n是什么?

为什么f(13)=6, 因为1,2,3,4,5,6,7,8,9,10,11,12,13.数数1的个数,正好是6.

请大家写出自己的算法,并统计一些在你机器上计算出1111111110的时间。为了不影响大家的思路,我最后贴上我的程序。

语言不限,随便了。
...全文
6156 207 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
207 条回复
切换为时间正序
请发表友善的回复…
发表回复
liulongsnow 2010-05-30
  • 打赏
  • 举报
回复
顶一下
cheng_xu_ren_sheng 2006-05-09
  • 打赏
  • 举报
回复
main()
{
long int a,b;
scanf("%ld\n",a):
printf("%ld\n",b=(f(10^n - 1) = 10^(n-1) + f(10^(n-1)) * 10)):
}
wanshuiqianshan 2005-11-09
  • 打赏
  • 举报
回复
// vc6测试,速度很快,1111111110,瞬间就出来了
// 非递归,归纳下 此酸法就3中情况, 0,1,和>=1 分别处理即可。

#include <iostream>
#include <windows.h>
#include <ctime>
using namespace std;

int f(unsigned int n);
int main(int argc, char* argv[])
{
int n=1111111110;
cout<<"f("<<n<<")="<<f(n)<<endl;

return 0;
}


int f(unsigned int n)
{
unsigned int temp1,temp2,count,i;
count=0;
i=1;
temp1=n;
while(temp1)
{
temp2=temp1%10;
temp1=temp1/10;

if(temp2==0)
{
count=count+temp1*i;
}
if(temp2==1)
{
count=count+temp1*i+n%i+1;

}
if(temp2>=2)
{
count=count+(temp1+1)*i;
}
i=i*10;
}
return count;
}

Dragon132 2005-11-02
  • 打赏
  • 举报
回复
mark
boy 2005-10-17
  • 打赏
  • 举报
回复
http://community.csdn.net/Expert/topic/4330/4330005.xml?temp=.620846
眼急手块 2005-10-17
  • 打赏
  • 举报
回复
运行 9223372036854775807 看看
guileen 2005-10-13
  • 打赏
  • 举报
回复
还有一个关键问题,如何证明n>1111111110时不会再有n使得f(n)=n了!!!
Pigwen 2005-10-12
  • 打赏
  • 举报
回复
学习
谭风华 2005-10-12
  • 打赏
  • 举报
回复
#include "stdafx.h"
using namespace std;

int find(int& a)
{
int i=0,j=0;
int b=a;
while(b!=0)
{
j=b%10;
if(j==1)
i++;
b=b/10;
}
return i;
}

int _tmain(int argc, _TCHAR* argv[])
{
int N,sum=1;
for(N=2;;N++)
{

sum=sum+find(N);

if(N==sum)
break;
}
cout<<N<<endl;
system("pause");
return 0;
}
一秒都不要!
bugatti 2005-10-12
  • 打赏
  • 举报
回复
我有个更简单的
jeng 2005-10-11
  • 打赏
  • 举报
回复
关于google那个问题,我已经找到了一个复杂度为常数的算法:f(n)=?,对于找到f(n)=n ,有思路,复杂度为lg(n),找个时间把详细的思路和源码奉上。
zhangzhenyu220 2005-10-05
  • 打赏
  • 举报
回复
我觉得程序应该返璞归真,写的越简单越好:

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

int main ( int argc, char * argv[] )
{
clock_t start, end;
int i,j, cnt = 0;

start = clock();
for ( i = 1; ; i++)
{
j = i;
while ( j > 0 )
{
if (j % 10 == 1) cnt ++;
j = j / 10;
}

if( i != 1 && cnt == i ) break;
}
// print the result
end = clock();
cout << "f(" << i<< ")=" << i <<"." <<endl;
cout << "The algorithm takes "<< end - start<<"("<< double (end -start ) / CLOCKS_PER_SEC <<" sec)" << " cpu clocks." <<endl;
return 0;
}
----------------------------------
程序输出如下:
f(199981)=199981.
The algorithm takes 62(0.062 sec) cpu clocks.
程序只用了 0.06秒,我觉得枚举就很快了。
dirdirdir3 2005-08-20
  • 打赏
  • 举报
回复
0-15毫秒了:
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#define MAX 4000000000
int main(int argc, char* argv[])
{
int startt;
unsigned int i=0,onecount=0;
unsigned int j,k,l,m,tmp;

startt=GetTickCount();
while(i<MAX)
{
//*
j=i;k=0;l=0;m=0;onecount=0;
while(j>0)
{
tmp=j%10;
onecount+=m*k*tmp;
if(tmp==1)
{
onecount+=l+1;
}
if(tmp>1)
{
if(m==0)
onecount+=1;
else
onecount+=k*10;
}
if(m==0)
{
k=1;
l=tmp;
}
else
{
k=k*10;
l+=k*tmp;
}
m++;
j=(j/10);
}
if(onecount==i)
{
printf("%d\n",i);
i++;
continue;
}
if(i>onecount)
{
if((i-onecount)/10>0)
i+=(i-onecount)/10;
else
i++;
continue;
}
if(i<onecount)
{
i=onecount;
continue;
}
}
printf("%d\n",GetTickCount()-startt);
return 1;
}
kenyle 2005-08-19
  • 打赏
  • 举报
回复
up
magic_laubj2008 2005-08-19
  • 打赏
  • 举报
回复
mark
Kevin_007 2005-08-19
  • 打赏
  • 举报
回复
再一次优化

---------------代码Start----------------
#include<iostream.h>
#include<windows.h>

void main()
{
long int Sum=0;
long int i;
long int j;
long int Num;
int beginTime=GetTickCount();
for(i = 1; i <1111111111; i++)
{
Num = i;

while(Num>9)
{
j=Num / 10;

if (Num - j * 10==1)
Sum++;

Num=j;
}

if(Num==1)
Sum++;

if(Sum==i)
cout << i <<endl;

}

int endTime=GetTickCount();
endTime-=beginTime;
cout<< " Timer is :" << endTime <<endl;
}
----------------------------------------
-----------------结果-------------------
1
199981
199982
199983
199984
199985
199986
199987
199988
199989
199990
200000
200001
1599981
1599982
1599983
1599984
1599985
1599986
1599987
1599988
1599989
1599990
2600000
2600001
13199998
35000000
35000001
35199981
35199982
35199983
35199984
35199985
35199986
35199987
35199988
35199989
35199990
35200000
35200001
117463825
500000000
500000001
500199981
500199982
500199983
500199984
500199985
500199986
500199987
500199988
500199989
500199990
500200000
500200001
501599981
501599982
501599983
501599984
501599985
501599986
501599987
501599988
501599989
501599990
502600000
502600001
513199998
535000000
535000001
535199981
535199982
535199983
535199984
535199985
535199986
535199987
535199988
535199989
535199990
535200000
535200001
1111111110
Timer is :553625
Press any key to continue
---------------------------------
寒扬1.8 win2000
hnqwe 2005-08-19
  • 打赏
  • 举报
回复
我的,有一部分是剽窃的,
#include<iostream.h>
#include<windows.h>

void main()
{
long int Sum=0;
long int i;
long int j;
long int Num;
int beginTime=GetTickCount();
for(i = 1; i <1111111111; i++)
{
//////////////////////////////////////////////////////
Num = i;
for(j = 0;j<9;j++)
{
if(Num%10 == 1)
Sum ++;
Num /= 10;
}
///////////////////////////////////////////////////
//以上就是主要的算法,很土

if(Sum==i)
cout << i <<endl;

}

int endTime=GetTickCount();
endTime-=beginTime;
cout<< " Timer is :" << endTime <<endl;
}
请高手指正
Leopard79 2005-08-19
  • 打赏
  • 举报
回复
好像最大的n就是1111111110!

假设n=a(t)a(t-1)...a(2)a(1) 其中t表示位数,设t = 101表示101位,那么
n > 100...0 (有100个0)并且 n < 99..9 (有101个9) < 1e101
又因为0到100...0(100个0)中的1的个数为100*100...0(99个0)= 1e101

由上可见如果超过100的话,n是不可能大于f(n)!

如下是我在100位内测试的结果!

1 0
2 1
3 199981
4 199982
5 199983
....
....
....
78 535199987
79 535199988
80 535199989
81 535199990
82 535200000
83 535200001
84 1111111110
85 29344946414936894071258740550938792421843805471735622133691506054161009177094788169262865510411980234
The time is : 562ms


第85位为最后一次比较的数,不满足条件!
由此可见在100位内1111111110是最大的!




QunKangLi 2005-08-19
  • 打赏
  • 举报
回复
昨天的回复没看清题意,汗~~~~
unsigned f(unsigned n) ;

int main( int argc, char ** argv )
{
unsigned i ;
for( i = 0 ; i != -1 ; ++i )
if( i == f(i) )
printf( "%d\n", i ) ;
printf ( "end.\n" ) ;
return 0 ;
}

unsigned f(unsigned n)
{
int c = 0, r = 0, b = 1, v;
while(n) {
v = n % 10 ;
n /= 10 ;
c += n*b ;
if( v ) c += v == 1 ? r+1 : b ;
r += b*v ;
b *= 10 ;
}
return c ;
}
加载更多回复(183)

70,020

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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