数论——质数

质数的基本概念

一个数只能被 1 1 1 和它本身整除,则为质数.

质数的基本性质

  1. 0 , 1 0,1 0,1既不是质数也不是合数.
  2. 2 2 2 是最小的质数.

质数判定

时间复杂度 O ( N ) O(\sqrt N) O(N )
原理:埃氏筛法,正整数 n n n 是素数,当且仅当它不能被任何一个小于等于 n \sqrt n n 的素数整除.
所以判定时,先特判 0 , 1 0,1 0,1 ,然后扫 2 − n 2-\sqrt n 2n

bool check(int x)
{
	int i;
	
	if(x<2)	return false;
	rep(i,2,x/i)	if(x%i==0)	return false;
	return true;
}

分解质因数

原理: n n n 中最多包含一个大于 n \sqrt n n 的质因子,最后别忘记特判 n > 1 n>1 n>1 的情况.

void getfactor(int x)
{
	int i,nums;
	
	for(i=2;i<=x/i;++i)
	{
		if(x%i==0)
		{
			nums=0;
			while(x%i==0)	++nums,x/=i;
			printf("%d %d\n",i,nums);
		}
	}
	
	if(x>1)	printf("%d %d\n",x,1);
	
	puts("");
}

线性筛质数模板

线性筛高效的原因:一个数只会被它最小的质因子筛掉

const int N=1e6+10;
int n,cnt;

int primes[N];
bool st[N];

void getprimes()
{
	int i,j;
	
	rep(i,2,n)
	{
		if(!st[i])	primes[cnt++]=i;
		for(j=0;primes[j]<=n/i;++j)
		{
			st[i*primes[j]]=true;
			if(i%primes[j]==0)	break;	
		}
	}
}

二次筛法

概念:要筛的数太大,不可能从 1 1 1 开始筛,因此要先筛根号范围.

首先引入一个重要性质:
若一个数 x x x 是合数,则必然存在两个因子 d d d n d \frac{n}{d} dn,则必然存在一个小于等于 n \sqrt n n 的因子.

问题背景:如何筛出 [ L , R ] [L,R] [L,R] 之间的质数,其中 R − L ≤ 1 0 6 R-L\le 10^6 RL106.

具体步骤如下:

  1. 首先筛出 int 范围内的所有质数.
  2. 然后就是求出 [ L , R ] [L,R] [L,R] 种最小的 p p p 的倍数,即 ⌈ L p ⌉ p \lceil \frac{L}{p}\rceil p pLp
  3. 关键结论,即上取整转化为下取整的操作,即 ⌈ L p ⌉ = ⌊ L + p − 1 p ⌋ \lceil\frac{L}{p}\rceil=\lfloor\frac{L+p-1}{p}\rfloor pL=pL+p1
  4. 要注意特判 L = 1 L=1 L=1 的特殊情况.

反质数

对于任何正整数 x x x,其约数的个数记作 g ( x ) g(x) g(x)
如果某个正整数 x x x 满足:对于任意的小于 x x x 的正整数 i i i,都有 g ( x ) > g ( i ) g(x)>g(i) g(x)>g(i),则称 x x x反素数

如何求反质数? 用搜索.

反质数的充要条件作为搜索的目标
反质数的必要条件作为搜索的剪枝的依据

充要条件:即为反质数的定义。
必要条件1:一个反素数的所有质因子必然是从2开始的连续若干个质数。
必要条件2:若 n n n 是反质数,且 n = 2 p 1 ∗ 3 p 2 ∗ 5 p 3 ∗ 7 p 4 ∗ . . . . n=2^{p_1}*3^{p_2}*5^{p_3}*7^{p_4}*.... n=2p13p25p37p4....,则 p 1 ≥ p 2 ≥ p 3 ≥ p 4 ≥ . . . . p_1\ge p_2\ge p_3\ge p_4\ge .... p1p2p3p4....

求不超过 N N N 的最大反素数

ll n,ans,nums;

ll primes[10]={2,3,5,7,11,13,17,19,23,29};

void dfs(int i,ll now_ans,ll now_nums,ll last)
{
    if(now_nums>nums||(now_nums==nums&&now_ans<ans)) //注意一定是小于,因为反质数的定义中是严格大于
        nums=now_nums,ans=now_ans;
    
    if(i==10)   return;
    
    ll k=0;     //当前质因子的个数
    
    while(1)
    {
        ++k;
        now_ans*=primes[i];
        
        if(k>last||now_ans>n)   return;
        
        dfs(i+1,now_ans,now_nums*(k+1),k);
    }
}

int main()
{
    int i,j;
    
    scanf("%lld",&n);
    
    dfs(0,1,1,0x3f3f3f3f);
    
    printf("%lld",ans);
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值