一、高精度计算
这一次课程主要讲了高精度加、减、乘。
首先,定义一个高精度的结构体,储存这个数字的长度、和这个数字本身。
1 struct gaojing 2 { 3 int n,z[2333]; 4 5 gaojing() 6 { 7 n=1; 8 memset(z,0,sizeof(z)); 9 } 10 11 void init() 12 { 13 scanf("%s",s+1); 14 int l=strlen(s+1); 15 reverse(s+1,s+l+1); 16 17 n = l; 18 for (int a=1;a<=n;a++) 19 z[a] = s[a]-'0'; 20 } 21 22 void print() 23 { 24 for (int a=n;a>=1;a--) 25 printf("%d",z[a]); 26 } 27 };
1、高精度加法
只需要将数字当做字符串读入,在一位一位地相加,考虑进位即可。
这里还需要注意的一点是,我们在写高精计算函数时,参数最好要读取地址,而不是直接读取字符串。这样如果这个字符串很大,参数进入时还要把这个很大的字符串复制一遍,既消耗时间,又消耗内存。
1 gaojing operator+(const gaojing &a,const gaojing &b) 2 { 3 gaojing c; 4 c.n = max(a.n,b.n); 5 for (int i=1;i<=c.n;i++) 6 c.z[i] = a.z[i] + b.z[i]; 7 for (int i=1;i<=c.n;i++) 8 { 9 c.z[i+1] += c.z[i]/10; 10 c.z[i] = c.z[i]%10; 11 } 12 if (c.z[c.n+1] != 0) c.n++; 13 return c; 14 }
2、高精度比较
1 bool operator<(const gaojing &a,const gaojing &b) 2 { 3 if (a.n!=b.n) return a.n<b.n; 4 for (int i=a.n;i>=1;i--) 5 if (a.z[i] != b.z[i]) return a.z[i]<b.z[i]; 6 return false; 7 }
3、高精度乘法
首先,根据十*十=百,十*百=千,千*万=千万可得:
i位*j位,结果要加到i+j-1位上。
最后,和高精度加法还有区别的一点是,这个要去除前导零。
1 gaojing operator*(const gaojing &a,const gaojing &b) 2 { 3 gaojing c; 4 c.n = a.n + b.n; 5 for (int i=1;i<=a.n;i++) 6 for (int j=1;j<=b.n;j++) 7 c.z[i+j-1] += a.z[i] * b.z[j]; 8 for (int i=1;i<=c.n;i++) 9 { 10 c.z[i+1] += c.z[i]/10; 11 c.z[i] = c.z[i]%10; 12 } 13 while (c.n != 1 && c.z[c.n] == 0) 14 c.n--; 15 return c; 16 }
4、高精度减法
其实思想和高精度加法差不多,只不过要判断正负(用刚才写的比较函数判断即可)。
代码就不再写了。
二、求最大公约数、最小公倍数。
可以用自带函数求最大公约数:
__gcd(a,b);
推荐使用手写最大公因数:
int gcd(int a,int b) { if (b==0) return a; else return gcd(b,a%b); }
最小公倍数的话,根据两个数相乘等于他们的gcd*lcm即可求得。
三、快速幂:
首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn),快了好多好多。它的原理如下:
假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时,a^11=a^(2^0+2^1+2^3)
1 int ksm(int x,int y,int p) 2 { 3 int ans=1; 4 while (y) 5 { 6 if (y&1) ans=1ll*ans*x%p; 7 x=1ll*x*x%p; 8 y>>=1; 9 } 10 return ans; 11 }
代码很短,死记也可行,但最好还是理解一下吧,其实也很好理解,以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a^(2^0) * a^(2^1) * a^(2^3),是从左向右的。我们不断的让base*=base目的即是累乘,以便随时对ans做出贡献。
其中要理解base*=base这一步,看:::base*base==base^2,下一步再乘,就是base^2*base^2==base^4,然后同理 base^4 * base4 = base^8 ,,,,, see?是不是做到了base-->base^2-->base^4-->base^8-->base^16-->base^32.......指数正是 2^i 啊,再看上面的例子,a¹¹ = a^(2^0) * a^(2^1) * a^(2^3),这三项是不是完美解决了,,嗯,快速幂就是这样。
四、矩阵内容
(这一部分我已经写过了,这里不再赘述)