1.二分算法
题目描述:输入n(n<100000)个整数,,找出其中两个数,,它们之和等于m(题目确保有解)。
解法1:
用两重循环,枚举所有的取数方法,复杂度是o(n²)
for(int i=0;i<n-1;++i)
for(int j=i+1;j<n;++j)
if(a[i]+a[j]==m)
break;
显然这种方法最容易想到,但是算法复杂度和时间都会超时,在poj根本无法提交。
解法2:
1)对数组先进行排序,复杂度是o(n×logn)
2)在使用二分查找算法,最多查找n-2次,复杂度也是o(n×logn)
所以总的复杂度也是o(n×logn),比解法一少了不少。
解法三:
1)还是将数组排序
2)查找的时候。不用二分,设置2个变量i,j,i的初值是0,j的初值n-1,,看a[I]+a[j],如果大于m,就让j-1,反之,就让i+1,直至找到结果。
这种方法和解2差不多,算法复杂度也是o(n×logn)
综上,每次解题时不可盲目解题,要找到复杂度合适的方法解决题目。
2.poj1423
问题描述:在许多应用中,需要非常大的整数。其中一些应用程序使用密钥来安全传输数据、加密等。在这个问题中,您将得到一个数字,您必须确定该数字的阶乘中的位数。
输入:
输出
思路:当数字较小时,题目还是可以通过简单的乘法算出,但是当数字越来越大时,就给用到别的方法,这里可以使用斯特林公式,专门用来计算阶乘的位数
代码片段:
#include <iostream>
#include <cmath>
using namespace std;
#define pi 3.1415926535898
typedef long long ll; 定义了一个长整型ll
ll steling(ll n) 长整型函数steling ,参数n阶乘
{
return ll(int(log10(sqrt(2.0*pi*m))+m*log10(m/e))+1)+1;
int main()
{
int n;
cin>>n; 行数输入
while(n--){
int m;
cin>>m; 输入阶数
if(m==1) 如果是一阶
cout<<1<<endl; 就直接输出1
else
cout<<steling(m)<<endl; 2阶以上都用用了斯特林公式的函数套用一下。
}
return 0;
}
这个公式在数学上是这样的:
log10(sqrt(2.0*pi*m))+m*log10(m/e))+1
将数学公式上下同时取对数,在用代码语言专用符号,就得到了上述公式
这种题目只要知道公式,就能很快解决问题,所以多知道学习掌握这种公式非常重要。
俞