题目大意:
求fibonacci数列的前面四位,注意f[0] = 0;
解题思路:
凡是要求数的前面几位的,都可以用两边求对数的思想。让我想起了,m = n^n.要求n的前面一位。这个时候用对数,
lg(m) = n*lg(n), m = pow(10, n*lg(n)),之后求n*lg(n)的小数部分,因为整数部分为10^P(p代表整数),全都为10000……,而小数部分则为10^B(B代表小数部分),所以要取几位,就去小数那里取即可。
这是网络上摘来的,写得very good:
先看对数的性质,loga(b^c)=c*loga(b),loga(b*c)=loga(b)+loga(c);
假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;
log10(1.0234432)就是log10(10234432)的小数部分.
log10(1.0234432)=0.010063744
10^0.010063744=1.023443198
那么要取几位就很明显了吧~
先取对数(对10取),然后得到结果的小数部分bit,pow(10.0,bit)以后如果答案还是<1000那么就一直乘10。
注意偶先处理了0~20项是为了方便处理~
这题要利用到数列的公式:an=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)
代码:
#include
#include
const double N1 = (1.0+sqrt(5.0))/2.0;
const double N2 = (1.0-sqrt(5.0))/2.0;
using namespace std;
int main(void)
{
int n;
int f[21];
f[0] = 0;
f[1] = 1;
f[2] = 1;
for(int i = 3; i < 21; i++)
f[i] = f[i-1] + f[i-2];
while(scanf("%d", &n) == 1)
{
if(n <= 20)
{
printf("%d\n", f[n]);
continue;
}
double temp1, temp2, ans;
temp1 = log10(1.0/sqrt(5.0));
temp2 = (double)n * log10(N1) + log10(1.0 - pow(N2,(double)n));
ans = temp1 + temp2;
ans = ans - (int)ans;
ans = pow((double)10, ans);
// printf("%lf\n", ans);
// printf("%lf\n", ans);
printf("%d\n", (int)(ans*1000));
}
return 0;
}
TLE代码:
//超时
#include
using namespace std;
const int MAX = 10005;
char str[MAX], str1[MAX], str2[MAX];
void add(char a[], char b[], char c[])
{
memset(c, '0', sizeof(c));
int len1, len2, len;
len1 = strlen(a);
len2 = strlen(b);
for(int i = len1-1, j = 0; i >= 0; i--, j++)
c[j] = a[i];
for(int i = len2-1, j = 0; i >= 0; i--, j++)
c[j] += b[i] - '0';
len = len1 >= len2? len1: len2;
for(int i = 0; i < len; i++)
{
if(c[i] > '9')
{
c[i] -= 10;
c[i+1] ++;
}
}
if(c[len] > '0')
len++;
c[len] = '\0';
strrev(c);
//for(int i = 0; i < len; i++)
// printf("%c", c[i]);
//printf("\n");
}
int main(void)
{
int n;
int cas;
/*strcpy(str1, "132424");
strcpy(str2, "123424234");
add(str1, str2, str);*/
scanf("%d", &cas);
while(cas--)
{
// scanf("%d", &n);
for(int n = 1; n < 30; n++)
{
strcpy(str1, "1");
strcpy(str2, "1");
if(n == 1 || n == 2)
{
printf("1\n");
continue;
}
for(int i = 3; i <= n; i++)
{
memset(str, '0', sizeof(str));
add(str1, str2, str);
strcpy(str1, str2);
strcpy(str2, str);
}
printf("%s\n", str);
}
}
return 0;
}