这个BLOG里有个JAVAEYE的两道题,其中的第二题,提供了一个解法,是减枝的办法。看完这个程序觉得写的比较繁琐一点,且没有任何注释,不容易看懂,所以这里重写程序基本思路一样,不过添加注释
总的来说就是举例来说,10到19,然后20-29,。。。到了100-199,这样递增数从10,100.。。
有兴趣的可以看看,linkhl好容易原创一个贴呵呵。。。
#define gsize 9
//save f(9),f(99),f(999),f(9999).....
unsigned long gtable[gsize];

unsigned long maxn=400000000L;
//initiate the gtable
void initGtable()
...{
int i=2;
int j,n=1;
for(i=2;i<gsize;i++)...{
// n=1;
// for(j=1;j<i;j++)
n*=10;
gtable[i]=gtable[i-1]*10+n;
}
}
//return count1 ,count how many 1 the n has
unsigned long count1(unsigned long n)...{
int cout=0;
while(n)...{
if((n%10)==1)...{
cout++;
}
n=n/10;
}
return cout;
}
//most important, countBefore presents the 1's numbers from 1 to number -1, count1now presents the number of 1 of number parameter,wei presents the valid digit
//number.
unsigned long cout(unsigned long number, unsigned long countBefore, unsigned long count1now, unsigned long wei)...{
unsigned long i,n,nwei,maxcount,gcount,nnumber;
if(wei==1)...{
if(number==countBefore+count1now)...{
printf("the fn is number %d ",number);
}
return countBefore+count1now;
}
n=1;
gcount=0;
nnumber=number;
for(nwei=wei-1;nwei>0;nwei--)...{n*=10;gcount++;nnumber/=10;}
maxcount=countBefore+gtable[gcount]+count1now*n;
//here we have cut a lot of branchs.
if((maxcount<number)||(number+n-1)<countBefore)return maxcount;
n/=10;
for(i=0;i<10;i++)
countBefore=cout(number+i*n,countBefore,((i)==1)?count1now+1:count1now,wei-1);
return countBefore;//returning maxcount is either ok
}




main()...{
unsigned long i,wei,temp,n,ret,count1now,countBefore;
gtable[0]=0;
gtable[1]=1;
initGtable();
for(i=2;i<gsize;i++)...{
printf("%d ",gtable[i]);
}
n=1;
wei=1;
ret=0;
count1now=1;
countBefore=0;
temp=1;
while(n<maxn)...{
countBefore=cout(n,countBefore,count1now,wei);//n=1,2,3,4,5,6,7,8,9,10,20,...90,100,200,...900,1000,2000,....
n+=temp;
if(!(n%temp)&&(n/temp)==10)
...{temp*=10;wei++;}//you have add temp 10times.
count1now=count1(n);
}
}
本文介绍了一种计算从1至某个大整数范围内特定数字(如1)出现次数的算法。通过递增数列及减枝优化,提高了算法效率。文中详细解释了算法流程,并附带实现代码。
1336

被折叠的 条评论
为什么被折叠?



