质数的筛选:
一、
Eratosthenes筛选 nloglogn
基于思想:
任意整数x的倍数2x,3x都不是质数。
优化:
在筛选中我们发现,2和3都会把6标记为合数,实际上,小于x^2的x倍的数在扫描更小的数时就已经被标记过了
void primes(int n)
{
bool v[n]; //合数标记
memset(v,0,sizeof(v));
for(int i=2;i<=n;i++)
{
if(v[i])continue;
printf("%d ",i);
for(int j=i;j<=n/i;j++)
v[j*i]=1;
}
}
二、线性筛选 o (n)
即使在优化后,埃氏筛选仍然会重复标记合数。例如12会被2标记,又会被3标记。根本原因在于我们没有确定出唯一产生12的方式。
步骤:
1、设数组v记录每个数的最小质因子。
2、依次考虑2~N之间每个数。
3、若v[i]=i,说明i是质数,把它保存下来。
4、扫描不大于v[i]的每个质数p,令v[ip]=p。因为p<=v[i],所以p就是合数ip的最小质因子。
每个合数i*p只会被它的最小质因子p筛选一次,时间复杂度为o(n)。
int v[maxn],prime[maxn];
void primes(int n)
{
memset(v,0,sizeof(v));
int m=0;
for(int i=2;i<=n;i++)
{
if(v[i]==0)
{
v[i]=i;
prime[++m]=i; //i是质数
}
//给当前的数i乘上一个质因子
for(int j=1;j<=m;j++)
{
//prime[j]有比i更大的质因子,或者超出n的范围,退出。
if(prime[j]>v[i]||prime[j]>n/i)break;
//prime[j]是合数i*prime[j]的最小质因子
v[i*prime[j]]=prime[j];
}
}
for(int i=1;i<=m;i++)
printf("%d ",prime[i]);
}
for(int i=2;i<=n;i++)
{
if(!v[i])
{
prime[++m]=i;
phi[m]=i-1;
}
for(int j=1;j<=m;j++)
{
if(prime[j]*i>n)break;
v[prime[j]*i]=1;
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[prime[j]]*prime[j];
break;
}
else
phi[i*prime[j]]=phi[prime[j]]*(prime[j]-1);
}
}
质因子的分解
试除法
void divide(int n)
{
int m=0;
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
p[++m]=i,c[m]=0;
while(n%i==0)n/=i,c[m]++;
}
}
if(n>1)p[++m]=n,c[m]=1;
for(int i=1;i<=m;i++)
printf("%d ^ %d",p[i],c[i]);
}
题目
已知正整数a0,a1,b0,b1,a 0 ,a 1 ,b 0 ,b1 ,设某未知正整数x 满足:
1. x 和 a 0 的最大公约数是 a 1 ;
2. x 和 b 0 的最小公倍数是b 1 。
Hankson 的“逆问题”就是求出满足条件的正整数xx。但稍加思索之后,他发现这样的xx
并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xx 的个数。请你帮助他编程求解这个问题。
解答一https://blog.csdn.net/nuclearsubmarines/article/details/77603154
解答二、
#include <stdio.h>
#include <string.h>
#define min(a,b) a>b?b:a
#define ll long long
ll read()
{
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
int prime[45000],v[45000];
int m;
void primes()
{
memset(v,0,sizeof(0));
for(int i=2;i<=45000;i++)
{
if(v[i]==0)
{
v[i]=i;
prime[++m]=i;
}
for(int j=1;j<=m;j++)
{
if(prime[j]>v[i]||prime[j]>45000/i)break;
v[i*prime[j]]=prime[j];
}
}
}
int get_num(ll a,ll b)
{
int num=0;
while(a%b==0)
{
a/=b;
num++;
}
return num;
}
int main()
{
primes();
int t=read();
while(t--)
{
ll a=read(),c=read(),b=read(),d=read();
if(d==1)
{
if(c==1)printf("1\n");
else printf("0\n");
continue;
}
int ma,mb,mc,md,mx;
ll ans=1;
for(int i=1;i<=m&&prime[i]<=d;i++)
{
if(d%prime[i]==0)
{
mx=0;
md=get_num(d,prime[i]);
ma=get_num(a,prime[i]);
mb=get_num(b,prime[i]);
mc=get_num(c,prime[i]);
while(d%prime[i]==0)d/=prime[i];
if(ma>mc&&mb<md&&md==mc)mx++;
else if(ma>mc&&mb==md&&mc<=md)mx++;
else if(ma==mc&&mb<md&&mc<=md)mx++;
else if(ma==mc&&mb==md&&mc<=md)mx=md-mc+1;
ans*=mx;
}
}
if(d>1)
{
mx=0;
md=get_num(d,d);
ma=get_num(a,d);
mb=get_num(b,d);
mc=get_num(c,d);
if(ma>mc&&mb<md&&md==mc)mx++;
else if(ma>mc&&mb==md&&mc<=md)mx++;
else if(ma==mc&&mb<md&&mc<=md)mx++;
else if(ma==mc&&mb==md&&mc<=md)mx=md-mc+1;
ans*=mx;
}
printf("%d\n",ans);
}
}