Topic Links:
http://poj.org/problem?id=2773
Main topic:
give you two integers n and K, and find the number of K and N (the number of things from small to large permutations), where
(1 <= m <= 1000000,1 <= K <= 100000000).
Problem Solving Ideas:
K is large, directly from small to large enumeration to find unrealistic, can only be two-point answer. A binary enumeration of all the number x in the [1,inf] range,
Find the number of 1~x in the range and N, if equal to K, it is the result.
Then consider the number of 1~x within the range of n-ary = x-1~x in the range of n-ary
The number of 1~x in the range and n is obtained by simple repulsion theorem.
AC Code:
#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)//two points answer {Mid = (left + right) >> 1; TMP = Solve (Mid); if (TMP >= K) right = Mid; else left = Mid + 1; } printf ("%i64d\n", left); } return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
POJ 2773 Happy 2006 "The principle of tolerance and repulsion"