质数
质数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数
判断一个数是不是质数,可以从2枚举到|sqrt(n)|试试是否可以被整除就好了
例题1
这道题其实就是著名的埃氏筛法,具体的思想之前接触过,这里不会再做赘述,注意一些细节,布尔会比整型站的空间小
计算机思想,更高效的方法批量处理数据
算术基本定理,p1e1×p2e2×…×pkek
但是埃筛仍然不是线性筛法,因为一个数会被筛掉很多次,会被访问很多次,要想让时间复杂度成为线性,就必须让一个数只会被一个质数筛掉
埃氏筛法
这种质数的筛选的方法的想法就是:任意一个整数x的倍数都不是质数,所以就把他们划掉,这里我们还得有一个优化,就是说任何一个数x的x倍x2之前都会被别的数划去,我们只需要划掉的时候从x2开始,进行一个一个划分
void pd(int n)
{
for(int i=2;i<=n;i++)
{
if(v[i]) continue;
cout<<i<<endl;
for(int j=i;j<=n;j++)
v[i*j]=1;
}
}
欧拉筛法
小的时候学习两层暴力求质数,然后学习埃筛,现在呢,对于1e7的题目,我们可能要用欧拉筛法了
欧拉筛法让一个数只会被一个质数筛掉一次,从而到达线性的目的
我们选择这个数为它的在最小的质因数
首先从2到n枚举自然数q(不一定是质数),再从小到大枚举比q小的质数p,筛掉pq,如果q是p的倍数,就跳出内循环
什么意思,首先我们使用一个数组记录这个区间内的质数,然后枚举比区间内的数小的质数,并且不断筛掉两个数的乘积,直到这个数是质数的倍数,为什么要强调倍数,因为不是倍数而大于的话,就i不能保证是最小的质因数
另外说一下,std::ios::sync_with_stdio(0)降低cin的输入时间
int prime[size];
int book[size];
void prime()
{
for(int i=2;i<=n;i++)
{
if(book[i]==0)
prime[++prime[0]]=i;//这里就是保存素数,prime0用来记录个数
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++)
{
book[i*prime[j]]=1;
if(i%prime[jk]==0)
break;
}
}
}
例题2
这道题是一道nb题,是一道自己推方程的题
说句人话 ,求1/x+1/y=1/n!的解的个数,我感觉这个题真的是太难了,已经把我整吐了
经过一夜的思考终于把这道题的做法想来出来了
我们只不过是按照因式分解的方法来进行一个配套
∵x+y/xy=1/n!
∴n!2=(n!2)-xn!-yn!+xy=(x-n!)(y-n!)
所以我们只需要求n!2的因子个数就好了
质因数分解
任何一个正整数都能被分解为有限质数的乘积,如何将这些质数求出来
我们可以在2~sqrt(N)的每一个数d,若d能整除N,就从n中除掉所有的因子d,同时累计除去d个数
在上述的过程中,能整除的一定是质数,最后就得到了结果
其实用短除就可以
void div(int n)
{
int n,i;
cin>>n;
for(int i=2;i<=n;i++)
while(n!=i)
if(n%i==0)
{
cout<<i<<endl;
n=n/i;
}
else
break;
}
威尔逊定理
如果p是一个素数,那么(p-1)!≡1(mod p)