质因数分解
关键:k一定为质因数;
遍历到i的时候如果i还没被筛掉的话i就是素数
int k=2,sum=0;
scanf("%d",&n);
while(n>1)
{
while(n%k==0)
{
n=n/k; //除的尽一直除;
sum++; //累计数量;
}
k++; //除不尽了除下一位k++;
}
埃氏筛 O(nloglogn)
筛倍数,将2,3,5... ...的倍数筛去
1.数组设置:存质数的数组 prime【】;标记数组 char book【】;
2.存储质数:未被标记的为质数;
3.for循环设置:for( int j=i*2; j<=n; j+=i ) { book[ j ]=1; }
j=i*2, j 从 i 的第2倍数递增;
j+=i,数 i 的第3,4,5..倍数;
#include<stdio.h>
#define N 100010
int prime[N],cnt; //大数组,全局变量
char book[N]; //桶标记,char类型利用字符串存大数
int main()
{
int n;
scanf("%d",&n); //2--n的质数
for(int i=2;i<=n;i++)
{
if(!book[i]) //未被标记的为质数
{
prime[cnt++]=i; //将素数存入数组
for(int j=i*2;j<=n;j+=i) //j=i*2,j从i的第二倍数递增,j+=i,数i的第3,4,5..倍数
book[j]=1; //标记
}
}
printf("%d",cnt);
return 0;
}
欧拉筛 O(n)
也是通过筛倍数降低时间复杂度,但不会像埃氏筛一样重复筛已筛过的数(线性)
1.数组设置:存质数的数组 prime【】;标记数组 char book【】;未被标记的为质数;
2.存储质数:未被标记的为质数;
3.for循环设置: j 遍历质数数组,i 为2--n所有数
for(int j = 0; prime[ j ] <= n / i; j ++) // i * prime[j] <= n
{
book[i * prime[j]] = 1; // 标记
if(i % prime[j] == 0) break; // prime[j]是 i 的最小质因子
}如:12==2*6==3*4;但if(i % prime[j] == 0) break;找到最小质因数则跳出循环
#include<stdio.h>
#define N 1000010
int prime[N],cnt;
char book[N];
int main()
{
int n;
scanf("%d",&n);
for(int i = 2; i <= n ; i ++)
{
if(!book[i]) prime[cnt++] = i; //如果i没被标记过,i就是素数
for(int j = 0; prime[j] <= n / i; j ++) // i * prime[j] <= n
{
book[i * prime[j]] = 1;
if(i % prime[j] == 0) break; //prime[j]是i的最小质因子
}
}
printf("%d",cnt);
return 0;
}
1.求连通图
基础并查集模板题
#include<stdio.h>
int fa[10010];
int cnt=0;
void init(int n)
{
for(int i=1; i<=n; i++)
{
fa[i]=i;
}
}
int find(int i)
{
if(i==fa[i]) return i;
else
{
fa[i]=find(fa[i]);
return fa[i];
}
}
void unionn(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
{
fa[x]=y;
cnt--;
}
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
init(n);
cnt=n;
while(m--)
{
int a,b;
scanf("%d %d",&a,&b);
unionn(a,b);
}
printf("%d\n",cnt);
return 0;
}
2. 只因数分解
题意:n==p*p*q;
输入n;输出p q;
坐牢一整天,已无语... ...
1.sqrt精度爆了,另写sqrtll;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define N 5000000+1000
long long prime[N],cnt;
char book[N];
long long sqrtll(long long x) //sqrt精度爆了,另写sqrtll
{
long double t=x; //这里用 long long double会报错
t=sqrtl(t+0.1);
return t;
}
int main()
{
long long i,j,temp=0;
for(i=2; i<=N; i++)
{
if(!book[i])
{
prime[cnt++]=i;
for(j=i*2; j<=N; j+=i)
{
book[j]=1;
}
}
}
int t;
scanf("%d",&t);
while(t--)
{
unsigned long long n;
scanf("%llu",&n);
for(i=0; i<cnt; i++)
{
if(n%prime[i]==0)
{
if((n/prime[i])%prime[i]==0)
{
printf("%lld %lld\n",prime[i],n/prime[i]/prime[i]);
}
else
{
long long p = sqrtll(n/prime[i]);
printf("%lld %lld\n",p,prime[i]);
}
break;
}
}
}
return 0;
}