描述
請你寫乙個程式,計算與m和n都互為素數的數中第k大的數,假如x與y互為素數,那麼x和y的最大公約數必為1。輸入
第一行包含乙個整數t代表測試資料的組數輸出每組資料有一行,分別包含m,n,k,其中(0
對應每組測試資料,每行輸出該組組號和第k個與m,n互為素數的整數思路:
對於1e9這樣的範圍,乙個乙個算出與m,n互質的數顯然不現實,思考o(log(n))的方法。設p(i)為小於等於i的正整數中與m,n互質數的個數,可以發現p(i)<=p(i+1),這個函式是遞增的,可以用二分來找出第k個與n,m互質的數。二分的下界為1,關於上界可以由素數定理(π(x)~x/ln(x))大致求出小於3e10的質數大約有1,243,550,985個,大於1e9,因此設上界為3e10。
接下來考慮計算p(i)的方法,參考n/2可以求出在1~n中可以被2整除的數量,因此可以求出n,m所有的質因子並利用容斥求出p(i)(加上所有i除以奇數個質數乘積的商然後減去所有i除以偶數個質數乘積的商,最後得到小於等於i中不與n,m互質的個數)。
考慮方案的時間複雜度。設n為質數個數,計算p(i)的複雜度為o(2^(n)),考慮n的最大值,nmax=2×3×5×7×11×13×17×19×23=223,092,870,mmax=29×31×37×41×43=58,642,669,nmax=14。
總複雜度為o(log2(3e10)*2^n)(去掉了計算質數的複雜度)在1<=n<=14的條件下最大值約為395,255,可行。
一開始用遞迴一直超時,後來發現才在求質數組合的時候多了很多重複計算……
#include
using
namespace std;
typedef
long
long ll;
const ll ms=
3e10+5
;int q[15]
,cnt;
void
cook
(int x)
if(xbreak;}
if(x!=
1)q[cnt++
]=x;
}ll m;
ll a[2]
[3500];
ll cul()
,it=0;
a[0]
[0]=
1;int st[2]
[3500]=
; ll ans=
0,tmp;
for(
int i=
0;i} c[it]=0
; it=
!it;
//cout(c[it]==0
)break;}
return ans;
}int
main()
//cout("case %d: %lld\n"
,no,l);}
return0;
}//1 223092870 58642669 1000000000
若有什麼錯誤,歡迎指正^ _ ^ 。 786 第 K 個最小的素數分數
乙個已排序好的表 a,其包含 1 和其他一些素數.當列表中的每乙個 p那麼第 k 個最小的分數是多少呢?以整數陣列的形式返回你的答案,這裡 answer 0 p 且 answer 1 q.示例 輸入 a 1,2,3,5 k 3 輸出 2,5 解釋 已構造好的分數,排序後如下所示 1 5,1 3,2 ...
N個元素陣列中第K大元素
k key.cpp 定義控制台應用程式的入口點。include stdafx.h include include using namespace std template int pivotindex t arr,int first,int last arr first arr last while...
求第K個素數 08年上海交大複試上機題第一題
08年上海交大複試上機題第一題 原題如下 problem a.prime number input file standard input output file standard output time limit 1 second output the k th prime number.inp...