算术数学知识准备篇

数学归纳法

证明P(1)
假设P(k)正确,证明 P(k+1)
证毕P(n)正确

int main()
{
  int sum=0;//sum代表前0个数字的和
  for(int i=0;i<=100;i++)
    sum=sum+i;//方程右边sum代表前i-1个数字的和,左边是i个数字的和
   cout<<sum<<endl;
}
int f(int n)
{
  if(n==1) return 1;//f(1)正确
  else return n*f(n-1);//假设f(n-1)正确->f(n)正确
}

了解数归更多是为了保证程序设计的正确性,迭代的程序可以用数学归纳法证明。

递归实现组合型枚举

题目:从1-n这n个整数中随机抽取m个,每种方案的数从小到大排列,按字典序输出可能的选择方案。

演示:3 2
输出:123 132 231

分析:求组合数的组合

int main()
{
  int n,m;
  cin>>n>>m;
  vector<int> buff;//临时存储区存储已经选择的数字
  output(n,m,1,buff);//第三位放置当前可以选择的数字的最小值
  return 0;
}

void output(int n,int m,int p,vector<int>& buff){
  if(m==buff.size())
  {
   for(int i=0;i<m;i++)
   {
      if(i!=0) cout<<" ";
      cout<<buff[i]
   }
  cout<<endl;
  return;
 }
 
 for(int i=p;i<=n;i++)
  {
  buff.push_back(i);
  output(n,m,i+1,buff);
  buff.pop_back();
  }
 return;
}

初等数论

素数筛

思路:
(1)首先将2到n范围内的整数写下来,其中2是最小的素数。将表中所有的2的倍数划去.
(2)表中剩下的最小的数字就是3,他不能被更小的数整除,所以3是素数,再将表中所有的3的倍数划去
(3)让每个合数只被它的最小质因子筛选一次,以达到不重复的目的

证明:合数=A*B(任何一个合数都可以用俩个不为1的素数标识,其中一个大于sqrt(n),另一个小于sqrt(n))

int prime[n+5]={0};
//prime[0]存储素数的个数
void prime()
{
  for(int i=2;i*i<=n;i++)
  {
   if(prime[i]) continue;
   for(int j=i*i;j<n;j+=i) prime[j]=1;
  }
  
  for(int i=2;i<=n;i++)
   if(prime[i]==0) 
    prime{++prime[o]]=i;
   return;
}

prime数组一分为二:
前半段到prime[0]之前存储素数表,之后存储素数的标记信息(素数筛)。

逆元+同余

1.俩个数字对相同的数字取余得到相同的余数
假设这个数字为A和B,此时我们假设认为这俩个数字相等。
A+d == B+d (mod n)
A-d == B+d (mod n)
A * d== Bd (mod n)
在这里插入图片描述
2.
在mod意义下,不能直接除以一个数,而要乘以它的逆元
逆元是d‘ 满足:d
d’=1(mod n)
a%b=a-kb k=(a/b)向下取整
在这里插入图片描述

欧几里得算法:

int gcd(int a,int b)
{
  if(b==0) return a;
  return gcd(b,a%b);
}

证明1:b和a%b的最大公约数,是a和b的公约数
证明2:b和a%b的最大公约数也是a和b的最大公约数
假设A和B互质,此时可以计算A在B下的逆元。
贝祖等式:Ax+By=gcd(a,b)=c

扩展欧几里得算法:
在这里插入图片描述

x*b+(a-kb)*y=c;
ay+(x-ky)*b=c;
//此时求得a和b的整数解
int ex_gcd(int a,int b,int &x,int &y)
{
   if(b==0){
    //最后一层
     x-1,y=0;
     return a;
   }
   int nx,ny;
   int r=ex_gcd(b,a%b,nx,ny);
   x=ny;
   y=nx-a/b*ny;
   return r;
}

int inv(int a,int b)
{
   int x,y;
   ex_gcd(a,b,x,y);//假设a和b一定互素,得到a和b的一组整数解
   x%=b;
   x+=b;
   x%=b;//使得x是个正数
   return x;
}
   

斐波那契推论

F(n+m)=F(m) F(n+1)+F(m-1) F(n)
尝试计算F(1e^15)%9973的值

递归令m=n=n/2

unoedered_map<int,int> f_result;
int f(int n)
{
  if(n<=2) return!!n;//归零化处理,如果n是0归零化后为0,其余数字归零化后为1
  if(f_result(n)!=f_result.end()){//记忆化思路
    int a=n/2,b=n-a;
    int val1=f(b),val2=f(a+1),val3=f(b-1),val 4=f(a);
    f_result(n)=(val1*val2+val3*val4)%9973;
}
  return f_result[n];
}    

快速幂算法

O(logN)
例如:求a^10;
(1)分解10为二进制:(1010),位权分别为8 4 2 1
(2)此时可以发现位权是8和2对应a^8 和 a^2
(3)此时用计算出a的一次到a的四次,再把a的平方和八次挑出来乘一次
(4)判断最后一位是奇数还是偶数来判断这个二进制数字末尾是0还是1

满足结合律均可使快速幂

int quick_power(int a,int b)
{
   int ans=1,temp=a;
   while(b){
      if(b%2) ans*=temp;
      temp*=temp;
      b/=2;
     }
     return ans;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太一TT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值