看了一天的数学,一些问题果真是比大多数算法比较难理解。
遇到了规律题、方法题、结论题还有技巧题。
看到的第一类题就是通过简单列举找到规律题,感觉这样的题需要多训练总结才有可能做出来。
有时候动手算也是非常必要。
例如分奇数偶数讨论啦、0和1特判啦、看是否是斐波那列数列和卡特兰数啦什么的,其中斐波那列数列变形形式很多
以前常用的就是1,1,2,3,5......利用a[n]=a[n-1]+a[n-2](n>=2),今天又学到了公式(r^n-s^n)/sqrt(5),其中r=(1+sqrt(5))/2
,s=(1-sqrt(5))/2.但是这个精度问题好像会出现问题吧,用的小点的数实验并没有问题,但是n一达到50以上就不会出正确结果了
做的对应的一个题就是这个:
对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在hanzhoufeng有一个很“简单”问题:第n项和第m项的最大公约数是多少?但是hanzhoufeng数学太烂了,只好去问上任数学课代表么么虫....但是么么虫也不会,只好来请教你了......
输入格式
两个正整数n和m。(n,m<=10^9)
输出格式
Fn和Fm的最大公约数。
首先用的就是那个公式,后来一想这样肯定不会对。查阅资料得知一个重要结论:gcd(fn,fm)=f(gcd(m,n)),这样就可以先打表后做了。
还有一个重要的题型就是素数问题
以前学了一种筛法:
memset(prime,1,sizeof(prime));
prime[0]=0;
prime[1]=0;
for(int i=2;i<=sqrt(1000000);i++)
{
if(prime[i])
for(int k=2;k<=1000000/i;k++)
{
prime[k*i]=0;
}
}
今天又看了另一种更加高效筛法:
int const n=1000000;
int prime[n]={0},num=0;
int isNotPrime[n]={1,1};
int main()
{
int i,j;
for(i=2;i<n;i++)
{
if(!isNotPrime[i])
prime[num++]=i;
for(j=0;j<num&&i*prime[j]<n;j++)
{
isNotPrime[i*prime[j]]=1;
if(!(i%prime[j]))
break;
}
}
}
也可以 这样:
bool isprime[1000010];
memset(isprime, true, sizeof(isprime));
for (int i = 4; i <= 1000000; i += 2)
// 所有大于 2 的偶数全都不是素数,首先划掉
isprime[i] = false;
for (int i = 2; i <= 1000000; i++)
{
if (isprime[i])
for (long long j = i * i; j <= 1000000; j += i + i)
isprime[j] = false;
}
还碰到了中国剩余定理,理解起来还行,用起来就不太好分析了,还是要多下功夫。最大公约数最小公倍数求法由以前的欧几里得算法现在知道了还能用二进制不断除2继续改进。当然还有一些难题需要逐步理解.......