2020 CCF-CSP备考习题总结

本文是作者在2020年CCF CSP备考过程中的学习总结,涵盖约瑟夫循环、三角形面积计算、质数算法、大数运算、进制转换等算法与C++基础知识,包括数据结构、动态规划、数论概念和STL使用等重点内容。
摘要由CSDN通过智能技术生成

本博客用于记录2020夏季小学期,CCF备考练习中学习、复习到的算法、数据结构、语法、常用方法等知识的特殊总结。着眼于解决暴露的缺陷,不能够解决全面的知识内容。同时数据结构P2可能暂时停止继续刊载复习。
!!!!
很奇葩 目录后面的 STL 部分显示不全 /哭
!!!!

算法

1:约瑟夫循环数学算法

题目描述:N个人围城一个圈子,最后一个人和第一个人相邻。从1开始报数,每隔M个人就淘汰一个人,问最后留下人的序号
(1)算法分析: 此类循环报数-淘汰问题可以统一使用约瑟夫数学算法,即F(n)=(F(n-1)+M)%N。其中F(1)=0,由此可以递归或者循环求得最后的坐标位数进而求得序号。
递推公式: F(n)=(F(n-1)+m)%n的求解方法
第一轮: m n 从0计数的位置大小中,m-1位置淘汰。由剩余的n-1个人构成n-大小的约瑟夫循环
此时,假设k位置成为首位,所以新的约瑟夫位置m–>0
m+1–>1
m+2–>2
.
.
.
m-2–>n-2
m-1–>n-1
若下一次淘汰对象位置在x位置,则x位置在第一次约瑟夫循环中,其位置是x’ = (x+m)%n
所以由于最后一次由1个大小构成的位置是0,即F(1)=0 F(2)=(0+m)%2 -->F(n)=(F(n-1)+m)%n
(2)算法实现

int main()
{
   
  int m,n; //间隔数 总人数
  cin>>n>>m;
  int pos=0;
  for(int i=1;i<=n;i++)
  r =(r+m)%i;
  cout<<r+1<<endl;
}

(3)注意事项:由于本算法计算的是位置坐标,而对象又是从1开始计数,所以对应序号应该是所得到的坐标+1(pos+1)

2:三角形面积求解的三种算法

题目:给定三角形的三个顶点的坐标,求解三角形的面积
(1)常用方法
方法一:海伦公式
S:面积 a,b,c:三条边的边长 p:三角形周长的一半
S =sqrt(p*(p-a)(p-b)(p-c))

方法二:向量内积的模
A,B,C为三角形的三个顶点 AB=(x2-x1,y2-y1) AC=(x3-x1,y3-y1) 此时|AB × AC| =|AB|*|AC|sin<AB,AC>为三角形面积的两倍。故
AB=(x2-x1,y2-y1) AC=(x3-x1,y3-y1)
S =1/2
|AB × AC|

方法三:平面解析几何法
S =| x1 y1 1 |
| x2 y2 1 | * 1/2
| x3 y3 1 |
=(x1y2+x2y3+x3y1-x2y1-x3y2-x1y3) * 1/2
注意:一般的面积用double浮点数类型存储即可

3:约数(求约数个数、求约数和

数论:正数唯一分解定理: 一个大于1的自然数,要么本身是质数,要么可以分解为两个或以上的质数的幂积。其公式表示为:
在这里插入图片描述
数论:约数个数定理: 一个正数的约数可能是质数,也可能是合数。根据质因数分解与Eratosthenes算法,我们能够得到质因数的个数。 同时其合数质因数同样可以表示为有限个质数的幂积。由此可以利用约数个数定理求解一个整数约数的个数。其公式表示为:
在这里插入图片描述
数论:约数和定理: 一个大于1的自然数,根据正数唯一分解定理可以分解为其质因数的幂积 A=p1^a1 + p2^a2 + p3^a3 +… 约数和定理可以表示该自然数所有约数的和。其公式表示为:
在这里插入图片描述

一般的,我们会使用到上述定理去求解指定数字的约数个数与约数和。
(1)约数个数定理求解约数个数
题目:给定数字N,求其约数的总个数
①要使用约数个数定理,就需要求解其各个质因数的幂。因此我们需要使用到质因数分解的方法。然后在带入公式求解约数个数。注意:当N本身为质数时,其公约数数目为2
②算法实现

int result =1;
int main()
{
   
	for(int k=2;k<=n/k;k++)
	{
   
	    int p =1;    //(1+a1)*....
   		if(n%k ==0)
   		{
   
      		while(n%k ==0)
	      	{
   
                n /=k;
                p++;
      		}
  	    }
  	    result *=p;        //实现连续的乘法
	}
	if(n >1) result =2;   //本身是质数
	cout<<result<<endl;
	return 0;
}

(2)约数和定理求约数和
①由约数和定理,N =(1+p1^1+ p1^2+ p1^3 +…+p1a1)*…(1+pk1+ pk^2+ …+pk^ak)。首先需要求解所有的质因数以及其乘积幂,所以需要使用质因数分解。最后带入公式,求解约数和。
②算法分析

int num =1;
int main()
{
   
   for(int k=2;k<=n/k;k++)  //质因数分解
   {
   
      int temp=1;           //存储单个(1+p1^1+p1^2...pq^a1)
      int prime=0;          //质因数
      if(n%k ==0)
      {
   
         prime =k;
         while(n%k ==0)
         {
   
             n /=k;
             temp =temp*prime+1;
         }
      }
      num *=temp;
   }
   if(n >1) num *=(1+x);   //本身为质数
   cout<<num<<endl;
   return 0;
}

4:质数(质因数分解、Eratosthenes算法

质数:一个大于1的自然数,除了1和它本身外,不能被其他自然数整除的数。 一般的,我们都会用到质数的判断统计,质数的筛选。
(1)Eratosthenes算法
题目:输入数字n,得到1-n的所有质数
①一般可以用于判断和筛选给定数字范围内的质数。 本方法是将给定数据范围内的数据进行标记,通过标记识别是否为质数。如果按照遍历试除法,我们需要注意遍历再逐一循环判断,这会有很大的时间开销。 因为质数的倍数一定是合数,所以我们可以通过直接对所找到质数的合数进行标记。同时又因为判断一般从2开始,2和3是天然的质数。由此我们就可以实现对所有质数合数的标记。同时为了方便计算与表示,我们将向量或数字从[1]位开始,跳过[0]位。所以一般要注意数组或者向量的大小n–>n+1
②算法实现

vecotr<int> con;
vector<int> prime_number;
int n_prime =0;
int main()
{
   
   int n;
   cin>>n;
   for(int i=0;i<=n;i++)
   con.push_back(0);    //所有数字初始化为0 [0,n]
   //质数为0 合数为1
   for(int i=2;i<=n;i++)
   {
   
      if(con[i] ==1) continue; //标记为合数
      n_prime++;               //质数计数器
      prime_number.push_back(i);//质数保存器
      for(int j=i;j<=n/i;j++)  //从i开始,前面的已经标记过了
      {
   
         con[i*j] =1;  //质数的倍数标记
      }
   }
   /*如此我们就可以得到全局范围内所有的质数(vector<int>prime_number)
   和范围内的质数个数了!
  */
}

数论-正数的唯一分解定理: 任何大于1的自然数,要么本身是质数,要么可以表示位两个或以上的质数的幂积。
公式 A=p1^k1 * p2^k2 * p3^k3…。
可以知道,当题目中要求得到该数用质数表述的质数的个数和情况、约数的个数与约数和等情况时,我们需要利用唯一分解定理和质因数分解得到相应质因数及其幂次大小。
(2)质因数分解 质因数+次数(+本身质数
题目:输入以大于一的整数n,求解用质数积表示的质数的个数
①根据唯一分解定理,该数得到的质数的乘积情况是唯一的。我们可以从质数2开始分解,如果还能分解就继续分解下去,并记录对应的个数。由于是天生的质数循环,所以我们得到的是质因数
②算法实现

vector<pair<int,int> > prime_factor_times;
int main()
{
   
    int n; 
    cin>>n;
    for(int i=2;i<=n;i++)
    {
   
       if(n%i ==0)   //是质因数
       {
   
          prime_factor_times.push_back(make_pair(i,0));
          //质因数i  次数0
          while(n%i ==0)
          {
   
             n /=i;
             prime_factor_times[i].second++; 
          }
       }
    }
    if(n >1) prime_factor_times.push_back(make_pair(n,
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冠long馨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值