数学基础

先转载一个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

原文地址:https://www.cnblogs.com/lbssxz/p/10673582.html