先转载一个markdown用法:(转载!)https://www.jianshu.com/p/191d1e21f7ed
切入正题:
高精度加法:
•先只考虑非负数的情况
•思路:模拟竖式运算
•注意:进位用c数组存储答案,用jinwei变量存进位,c[i+1]+=jw;
•优化:压位:原理:把四位或更多位看成一位存在数组a,b的一个空内,一次算一个4位数。压了4位复杂度O(n/4),n位就为O(n/n(前后n不一样的意义))
高精度减法:
•先只考虑非负数的情况:减数小于被减数
•思路:同加法类似,模拟竖式运算,进位变为退位
•注意:结果为负数的情况:先取正号,把负号提出来,算到结尾判定是否为负,如果是那就加上负号
•减数是负数:减数取负,变为加法
•都是负数:都取负,变为减法,即(-减数)-(-被减数)
高精乘法怎么办?
•统计负数个数s
•都变为非负数计算,若s为奇数,最后取负
•高精度除单精度(不要问我为什么,姚班钟神(%他)告诉我们用不着高精除以高精)
•A / B
•同理,模拟除法竖式即可。
模意义下运算-性质
•满足基本的交换律、分配率、结合律(记住矩阵乘法 不 满 足 !)
•对中间结果取模不影响最终答案
•5*5*5 mod 7 = 6 (125除以7=16...6)
•(5*5 mod 7)*5 mod 7 = 4*5 mod 7 = 6(余数乘5再%7)
快速幂:
计算a^b % c = ?
快速幂:

没错那个老师打错了(蒟蒻只是截图),。原理就一条:判断指数二进制编码最后一位是否是1(利用的1,2,4,8,16....的2的n次方)(大家都知道每个数都能拆成某一个数的n次方,n-1次方。。。。相加的形式)
最后b/=2等于b>>=1;目的是去掉最后一位;
费马小定理:
a^p-1同余1(在mod p意义下 );即a^phi(p)同余1(mod p);

最大公约数:
将两个数分解质因数,其中存在最大的质因数乘积c,使得c|a并且c|b,则c为最大公因数。c++用函数gcd来求最大公因数。
辗转相除法(又名欧几里德算法):
int gcd(int a,int b) { if(b==0)return a; gcd(b,a%b); }
逻辑图如下:
质数判别:
sqrt(根号判别):
bool judge(int a)//判定a是否为质数,用bool { for(int i=2;i<=sqrt(a);i++)//因子从2开始,枚举(从1开始那a%1肯定为0,那么任何数都不是质数了) if(a%i==0)return 0;//如果枚举到一个因子,直接返回假,退出不往后执行了 return 1;//如果从2到sqrt(a)都没有a的因子,那么a肯定为质数,返回真 }
此方法适合判定某一个数为质数(多了容易TLE。QAQ)
埃拉托斯特尼筛法:(埃氏筛法)
//代码如下(耐心点) #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <vector> #include <algorithm> using namespace std; const long long maxn = 10000007 + 10; const long long maxp = 700000; int vis[maxn]; // i是合数vis为1,i是素数,vis为0 long long prime[maxp]; void sieve(long long n){ long long m = (long long)sqrt(n + 0.5); memset(vis, 0, sizeof(vis)); vis[2] = 0; for (long long i = 3; i <= m; i += 2) { if(!vis[i]) for (long long j = i * i; j <= n; j += i) vis[j] = 1; if(i * i > n) break; } } long long gen(long long n){ sieve(n); long long c = 1; prime[0] = 2; for (long long i = 3; i <= n; i += 2) if(!vis[i]) prime[c++] = i; return c; } int main() { long long n, c; cout << "刷素数到n:"; cin >> n; c = gen(n); for (long long i = 0; i < c; i++) printf("%lld", prime[i]); cout << endl << c; return 0; }
原理:埃氏筛法适合求某一个范围的数是否为质数。利用质数的定义(除了1和自己之外,没有其他的因子)将某一范围的数从2开始,筛去2的倍数,3的倍数,4的倍数。。。筛到n的倍数,剩下没有被筛去的数处自己和1以外,没有其他的因子,那么这个数就是质数。
那么问题来了!有的数是2和3的公倍数,有的是13和5的公倍数,有的是2,3,7,的公倍数。。。 那么,一个数被筛去了两次以上,就会有重复的情况!时间复杂度也跟着增加,万一数据很大,TLE不是梦想!(QWQ)
那么怎么办?
线性筛法走起(保证了每个数只被最小质因数筛去一次,复杂度O(n))
#include<cstdio> #include<cstring> #define MAXN 100005 #define MAXL 1299710 int prime[MAXN]; int check[MAXL]; int tot = 0; memset(check, 0, sizeof(check)); for (int i = 2; i < MAXL; ++i) { if (!check[i]) { prime[tot++] = i; } for (int j = 0; j < tot; ++j) { if (i * prime[j] > MAXL)//i为当前的数,prime【j】为质数表中第j个数 { break; } check[i*prime[j]] = 1; if (i % prime[j] == 0)//重点在这,他保证了能够被最小质因数筛掉 { break; } } }
第一天内容完结撒花✿✿ヽ(°▽°)ノ✿QAQ
希望对各位大佬的学业有帮助QWQ