Acwing 196.質數距離 197.階乘分解
196.質數距離
題目描述
給定兩個整數L和U,你需要在閉區間[L,U]內找到距離最接近的兩個相鄰質數C1和C2(即C2-C1是最小的),如果存在相同距離的其他相鄰質數對,則輸出第一對。
同時,你還需要找到距離最遠的兩個相鄰質數D1和D2(即D1-D2是最大的),如果存在相同距離的其他相鄰質數對,則輸出第一對。
輸入格式
每行輸入兩個整數L和U,其中L和U的差值不會超過1000000。
輸出格式
對於每個L和U ,輸出一個結果,結果佔一行。
結果包括距離最近的相鄰質數對和距離最遠的相鄰質數對。(具體格式參照樣例)
如果L和U之間不存在質數對,則輸出“There are no adjacent primes.”。
資料範圍
1≤L<U≤2^31−1
輸入樣例:
2 17
14 17
輸出樣例:
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.
題目分析:由於L、R的範圍太大,所以我們不可能用線性篩法去求出所有的素數,然後比較;但是題目中還有一個資訊,那就是L到R的距離最多為10^6,而且我們知道一點:一個合數n一定存在一個小於等於√n的質因子,所以我們可以求出質因子p,然後根據質因子p找出[L,R]中所有的合數,那麼剩下的就是質數了。
現在問題是如何根據質因子p(對於質因子p,我們可以根據線性篩法找到[1,50000]中所有的質數,因為2^31開根號大約為50000)找出合數。
程式碼:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
#define N 1000010
bool vis[N];
long long int prime[N],cnt;
void Prime(int n)
{
memset (vis,false,sizeof(vis));//全部初始化為是素數
vis[0]=true;
vis[1]=true;
cnt=0;
for(int i=2; i<=n; i++)
{
if(!vis[i])
prime[cnt++]=i;
for(int j=0; j<cnt&&i*prime[j]<=n; j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
{
break;
}
}
}
}
int main()
{
int l,r;
while(cin>>l>>r)
{
Prime(50000);
memset(vis,false,sizeof(vis));//重複利用vis陣列
for(int i=0; i<cnt; i++)
{
long long p=prime[i];
/*檢索[l,r]上p的倍數,並標記為合數,有可能會碰到l=1(l,r很小,p在l到r的範圍內)的情況,即j=p,
這樣就會誤把質數p標記為合數,所以要至少從2*p開始*/
for(long long int j=max(2*p,(l+p-1)/p*p); j<=r; j+=p)
{
vis[j-l]=true;//標記為合數,並離散化,因為l和r的範圍很大,有10的9次方級別,所以要進行離散化處理,否則會超陣列範圍
}
}
cnt=0;//重複利用cnt
for(int i=0; i<=r-l; i++)
{
if(!vis[i]&&i+l>=2)//1即不是合數也不是質數,所以要特判
{
prime[cnt++]=i+l;
}
}
if(cnt<2)
{
cout<<"There are no adjacent primes."<<endl;
}
else
{
int maxx=0,minn=0;
for(int i=0; i<cnt-1; i++)
{
int d=prime[i+1]-prime[i];
if(d>prime[maxx+1]-prime[maxx]) maxx=i;
if(d<prime[minn+1]-prime[minn]) minn=i;
}
printf("%lld,%lld are closest, %lld,%lld are most distant.\n",prime[minn],prime[minn+1],prime[maxx],prime[maxx+1]);
}
}
return 0;
}
197. 階乘分解
題目描述
給定整數 N ,試把階乘 N! 分解質因數,按照算術基本定理的形式輸出分解結果中的 pi 和 ci 即可。
輸入格式
一個整數N。
輸出格式
N! 分解質因數後的結果,共若干行,每行一對pi,ci,表示含有pi和ci項。按照pi從小到大的順序輸出。
資料範圍
1≤N≤106
輸入樣例:
5
輸出樣例:
2 3
3 1
5 1
樣例解釋
5!=120=23∗3∗5
題目分析:首先找出1-n中所有的質數(線性篩法),1-n中所有質數必然全部都為n!的質因子。首先我們要先知道1-n中有多少個p(1-n中的質數)的倍數,1-n中有ceil(n/p)個p的倍數,每個p的倍數都至少存在一個p的指數次方,每個p的平方都至少存在兩個p的指數次方,每個p的三次方都至少存在三個p的指數次方…,所以p的ci等於
(在計算ceil(n/p)時相當於漏算了一個p^2的指數次,兩個p ^3的指數次。。。)
程式碼:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
#define N 1000010
int vis[N];
int prime[N],cnt;
void Prime(int n)
{
memset(vis,0,sizeof(vis));
vis[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
prime[cnt++]=i;
}
for(int j=0;j<cnt&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
break;
}
}
}
}
int main()
{
int n;
cin>>n;
Prime(n);
for(int i=0;i<cnt;i++)
{
int t=n,p=prime[i];
int sum=0;
while(t)
{
sum+=t/p;
t/=p;//代替n/p,n/(p^2),n/(p^3)....
}
cout<<p<<" "<<sum<<endl;
}
return 0;
}