標籤:1.0 思路 space poj span ble sof 簡單的 app
題目連結:
http://poj.org/problem?id=2773
題目大意:
給你兩個整數N和K。找到第k個與N互素的數(互素的數從小到大排列)。當中
(1 <= m <= 1000000,1 <= K <= 100000000 )。
解題思路:
K非常大,直接從小到大枚舉找出不現實,僅僅能二分答案。二分枚舉[1。INF]範圍內全部的數x,
找到1~x範圍內與N互素的數個數。假設等於K,則就是結果。
然後考慮1~x範圍內與N互素的數個數 = x - 1~x範圍內與N不互素的數個數
1~x範圍內與N不互素的數個數用簡單的容斥定理來求就可以。
AC代碼:
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#define LL __int64using namespace std;const LL INF = 0xfffffff0;int Prime[1000010],ct,N;void Divide(){ ct = 0; int n = N; for(int i = 2; i <= sqrt(n*1.0); ++i) { if(n % i == 0) { Prime[ct++] = i; while(n % i == 0) n /= i; } } if(n != 1) Prime[ct++] = n;}LL Solve(int n){ LL ans = 0; for(int i = 1; i < (1 << ct); ++i) { LL odd = 0; LL tmp = 1; for(int j = 0; j < ct; ++j) { if((1 << j) & i) { odd++; tmp *= Prime[j]; } } if(odd & 1) ans += n/tmp; else ans -= n/tmp; } return n - ans;}int main(){ int K; while(~scanf("%d%d",&N,&K)) { Divide(); LL Left = 1, Right = INF, Mid, tmp; while(Left < Right) //二分答案 { Mid = (Left + Right) >> 1; tmp = Solve(Mid); if(tmp >= K) Right = Mid; else Left = Mid + 1; } printf("%I64d\n",Left); } return 0;}
POJ2773 Happy 2006【容斥原理】