ICPC训练联盟2021寒假冬令营(9)_2021.01.29_笔记

这篇博客介绍了数论和组合分析的编程实验,包括素数运算、不定方程和同余方程的求解,以及如何使用算法解决这些问题。还探讨了如何生成排列和组合,以及如何按字典序生成下一个排列。内容涵盖Goldbach's Conjecture等经典问题的解题思路和代码实现。
摘要由CSDN通过智能技术生成

试题链接

点我进入代码提交OJ

学习笔记 - 数论与组合分析入门

数论的编程实验

• 3.1素数运算的实验范例
• 3.2求解不定方程和同余方程的实验范例
• 3.3 特殊的同余式
• 3.4 积性函数的实验范例
• 3.5 高斯素数的实验范例

3.1素数运算的实验范例

• 3.1.1 使用筛法生成素数的实验范例
• 3.1.2 测试大素数的实验范例

3.1.1 使用筛法生成素数的实验范例

• 计算整数区间[2,n]中的所有素数的最为简便的筛法——埃拉托斯特尼筛法(The Si
eve of Eratosthenes):
• 设u[]为筛子,初始时区间中的所有数在筛子u[]中。按递增顺序搜索u[]中的最小数,
将其倍数从u[]中筛去,最终筛中留下的数即为素数。

int i, j, k;
for (i=2; i<=n; i++)
	u[i]=true; //初始时所有数在筛中
for (i=2; i<=n; i++) //顺序搜索筛中的最小数
	if (u[i])
	{
   
		for (j=2; j*i<=n; j++) //将i的倍数从筛中筛去
			u[j*i]=false;
	}
for (i=2; i<=n; i++)
	if (u[i])//将筛中的所有素数放入su[]中
	{
    
		su[++num]=i;
	}

• 上述算法的时间复杂度为O(n * log log n)。算法中合数是作为素数的倍数被筛去的。

• 如果每个合数仅被它最小的质因数筛去,则算法效率可以大幅提升。由此引
出一种优化的算法——欧拉筛法(Euler’s Sieve):

int i, j, num=1;
memset(u, true, sizeof(u));
for (i=2; i<=n; i++)//顺序分析整数区间的每个数
{
    
	if (u[i])
		su[num++]=i; //将筛中最小数送入素数表
	for (j=1; j<num; j++)//搜索素数表的每个数
	{
    
		if (i*su[j]>n)
			break; //若i与当前素数的乘积超出范围,则分析下一个整数i
		u[i*su[j]]=false; //将i与当前素数的乘积从筛子中筛去
		if (i%su[j]==0)
			break; //若当前素数为i的最小素因子,则分析下一个整数i
	}
}

• 欧拉筛法的时间复杂度可优化至O(n)。

• 欧拉筛法证明如下:
• 设合数最小素因子为,它的另一个大于的素因子为′,令= = ′
′。
• 观察上面程序片段,可以发现循环到素因子时,合数第一次被标记
(若循环到之前已经跳出循环,说明有更小的素因子)。若也被′
标记,则是在这之前(因为′< ),考虑循环到′,注意到= = ′
′且和′为不同的素因子,因此| ′,所以当循环到素因子后结束,
不会循环到′,这就说明不会被′筛去。

3.1.2 测试大素数的实验范例

在这里插入图片描述
在这里插入图片描述

3.2求解不定方程和同余方程的实验范例

• 3.2.1计算最大公约数和不定方程
• 3.2.2 计算同余方程和同余方程组
• 3.2.3 计算多项式同余方程

3.2.1计算最大公约数和不定方程

在这里插入图片描述
在这里插入图片描述
• 定义3.2.1.1(线性组合). 如果a和b都是整数,则ax+by是a和b的线性组合,其中数x和y是整数。
• 定理3.2.1.1 如果a和b都是整数,且a和b不全为0,则GCD(a, b) 是a和b的线性组合中最小正整数。
• 证明:设c是a和b的线性组合中最小正整数,ax+by=c,其中数x和y是整数。由带余除法,a=cq+r,其中0<=r<c。由此可得r=a-cq=a-q(ax+by)=a(1-qx)-bqy。所以,整数r是a和b的线性组合。因为c是a和b的线性组合中最小正整数,0<=r<c,所以r=0,则c是a的约数。同理可证,c是b的约数。因此,c是a和b的公约数。
• 对于a和b的所有约数d,因为ax+by=c,所以d是c的约数,c>=d。所以c是a和b的最大公约数GCD(a, b)。
• 定理3.2.1.2 (Bezout定理). 如果a和b都是整数,则有整x和y使得ax+by= GCD(a, b)。
• 设a和b分别是9和6,它们的线性组合是9x+6y。GCD(9,6)=3,根据Bezout定理,存在x和y,使得9x+6y=3。
• 推论3.2.1.1 整数a和b互素当且仅当存在整数x和y使得ax+by=1。
在这里插入图片描述
在这里插入图片描述
• 定理3.2.1.3 设a, b和c都是整数。如果c不是GCD(a, b)的倍数,则不定方程ax+by=c没有整数解;如果c是GCD(a, b)的倍数,则不定方程ax+by=c有无穷多整数解。如果(x0, y0)是ax+by=c的一个整数解,则ax+by=c的所有整数解是x= x0+ k (b DIV GCD(a, b)),y= y0-k (aDIV GCD(a, b)),其中k是整数。
• 证明:设(x, y)是ax+by=c的一个整数解。如果c不是GCD(a,b)的倍数,那么ax+by=c就没有整数解。如果c是GCD(a, b)的倍数,由定理3.2.1.1,存在整数s和t,as+bt= GCD(a, b)。因为c是GCD(a, b)的倍数,所以存在整数e,c=e
GCD(a, b),c= e
(as+bt)= a*(se)+b*(te)。因此x0= se,y0= te是方程的一个解,ax0+by0=c。
• 令x= x0+ k (b DIV GCD(a, b)),y= y0-k (a DIV GCD(a, b)),其中k是整数。则ax+by= ax0+ak(b DIV GCD(a, b))+by0-bk(a DIV GCD(a, b))=ax0+by0=c。
• 因此,命题成立。
• 给出不定方程ax+by=c,其中a,b和c是整数常量,x和y是整数变量,而且x∈[xl, xr],y∈[yl, yr],要求计算方程的整数根(x, y)。求解算法如下。

• 方法1. 枚举
• 枚举每对(x, y),找出整数根。也就是说,计算不定方程(xrxl+1)*(yr-yl+1)次。

• 方法2. 扩展的欧几里得算法
• 对于不定方程ax+by=c,如果c不是GCD(a, b)的倍数,则不定方程无解,否则扩展的欧几里得算法用于求解。
• 设d= GCD(a, b),a’=a DIV d,b’=b DIV d,并且c’=c DIV d。则不定方程ax+by=c可以被等价地写为a’x+b’y=c’,GCD(a’, b’)==1。采用扩展的欧几里得算法求解a’x+b’y=1,(x’, y’)是整数根。设x0=x’c’,y0=y’c’,则(x0, y0)是ax+by=c的一个解,也就是说,ax0+by0=c。所以,a(x0+b)+b(y0-a)=c,a(x0+2b)+b(y0-2a)=c,......,a(x0+kb)+b(y0-ka)=c,k是整数。所以,不定方程ax+by=c的通解是x= x0+kb,y= y0-ka,k是整数。

组合分析的编程实验

• 1、排列的生成
• 2、排列和组合的计数
• 3、容斥原理与鸽笼原理
• 4、波利亚定理
• 5、生成函数与递推关系
• 6、快速傅里叶变换(FFT)

4.1 生成排列的实验范例

• 按字典序思想生成下一个排列
• 按字典序思想生成所有排列

4.1.1按字典序思想生成下一个排列

在这里插入图片描述
在这里插入图片描述

4.1.2 按字典序思想生成所有排列

• 在按字典序生成下一个排列的基础上,可得出生成所有排列的方法:
• 将最小字典序的排列作为第1个排列;然后反复使用字典序思想生成下一个排列,直至最后的正序不存在,即最大字典序的排列已生成为止。

4.2 排列组合计数的实验范例

• 【1】一般的排列组合计数公式
• 【2】两种特殊的排列组合计数公式
• 【3】多重集的排列数和组合数

4.2.1 一般的排列组合计数公式

在这里插入图片描述
在这里插入图片描述

A - Goldbach’s Conjecture (POJ 2262, ZOJ 1951, UVA 543)

In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture:
Every even number greater than 4 can be
written as the sum of two odd prime numbers.

For example:
8 = 3 + 5. Both 3 and 5 are odd prime numbers.
20 = 3 + 17 = 7 + 13.
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.

Today it is still unproven whether the conjecture is right. (Oh wait, I have the proof of course, but it is too long to write it on the margin of this page.)
Anyway, your task is now to verify Goldbach’s conjecture for all even numbers less than a million.
Input
The input will contain one or more test cases.
Each test case consists of one even integer n with 6 <= n < 1000000.
Input will be terminated by a value of 0 for n.
Output
For each test case, print one line of the form n = a + b, where a and b are odd primes. Numbers and operators should be separated by exactly one blank like in the sample output below. If there is more than one pair of odd primes adding up to n, choose the pair where the difference b - a is maximized. If there is no such pair, print a line saying “Goldbach’s conjecture is wrong.”
Sample Input
8
20
42
0
Sample Output
8 = 3 + 5
20 = 3 + 17
42 = 5 + 37

中文释义

在这里插入图片描述
在这里插入图片描述

解题分析

在这里插入图片描述

解题代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 1000010
int p[N];
void IsPrime()
{
   
    memset(p,0,sizeof(p));//假设所有数都为素数
    for(int i = 2; i<N; i++)
        if(!p[i])//如果i 是素数,则i 的倍数都为非素数
            for(int j = i+i; j<=N; j+=i)
                p[j] = 1;//非素数
}
int main()
{
   
    IsPrime();//提前打表
    int n,a,b;
    while(~scanf("%d",&n) && n)
    {
   
        a = 0;
        b = 0;
        for(int i = 2; i<n; i++)
            if(!p[i] && !p[n
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值