Guest User

Untitled

a guest
Feb 20th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.39 KB | None | 0 0
  1. /*
  2. * =====================================================================================
  3. *
  4. * Filename: 920G.cpp
  5. *
  6. * Description: codeforces 920G: List Of Integers
  7. *
  8. * Version: 1.0
  9. * Created: 2018年02月07日 12時48分22秒
  10. * Revision: none
  11. * Compiler: gcc
  12. *
  13. * Author: lionking
  14. * Organization: None
  15. *
  16. * =====================================================================================
  17. */
  18.  
  19. #include <cstdio>
  20. #include <vector>
  21.  
  22.  
  23. using namespace std;
  24.  
  25.  
  26. /*****************************************************************************************
  27. * Generate prime table
  28. * Given a threshold, this function will generate list all primes less than the threshold.
  29. *
  30. * Parameter:
  31. * 1. prime: the resultant prime table
  32. * 2. limit: the given threshold
  33. *
  34. * Return value:
  35. * Number of primes in the generated prime table
  36. *****************************************************************************************/
  37. template <typename T>
  38. size_t GeneratePrime(std::vector<T> &prime, const size_t limit)
  39. {
  40. prime.clear();
  41. std::vector<bool> check(limit, true);
  42.  
  43. /* check[i] = false: prime else not prime *
  44. * mask all even number to be not prime */
  45. check[0] = check[1] = false;
  46. for (int i = 4; i < limit; i += 2) check[i] = false;
  47. for (int i = 9; i < limit; i += 3) check[i] = false;
  48.  
  49. prime.push_back(2);
  50. prime.push_back(3);
  51. for (int i = 5; i<limit; i += 2) {
  52. if (check[i]) {
  53. /* is prime */
  54. prime.push_back(i);
  55. for (int j = i*i; j<limit; j += i) { check[j] = false; }
  56. }
  57. }
  58.  
  59. return prime.size();
  60. }
  61.  
  62.  
  63. /**********************************************************************************************
  64. * Euler Totient Function : phi(n)
  65. * This function will generate a table containing phi(i)
  66. *
  67. * Parameter list:
  68. * 1. phi: resultant table containing phi(i)
  69. * 2. limit: threshold. Only positive integers less than this threshold will generate phi(i)
  70. * 3. prime: prime tables with all primes less than the given threshold (namely, 2nd parameter)
  71. *
  72. * Return value:
  73. * None
  74. **********************************************************************************************/
  75. template <typename T>
  76. void euler_totient(std::vector<T>& phi, const size_t limit, const std::vector<T>& prime)
  77. {
  78. const auto primecount = prime.size();
  79. phi.clear();
  80. phi.resize(limit, 0);
  81. phi[1] = phi[2] = 1;
  82.  
  83. for(int i=3; i<=limit; ++i){
  84. int temp = phi[i] = i;
  85. for(int j=0; (j<primecount) && (prime[j]*prime[j]<=temp); ++j){
  86. if(!(temp%prime[j])){
  87. phi[i] = (phi[i]/prime[j])*(prime[j]-1);
  88. while(!(temp%prime[j]))
  89. temp /= prime[j];
  90. }
  91. }
  92. if(temp!=1)
  93. phi[i] = (phi[i]/temp)*(temp-1);
  94. }
  95. }
  96.  
  97.  
  98. /****************************************************************************************************
  99. * Prime Factorization
  100. * Given a positive integer n = p1 ^ k1 * p2 ^ k2 * ... * pm ^ km, where p1, p2, ... , pm are primes,
  101. * this function will return the list {p1, p2, ... , pm}
  102. *
  103. * Parameters:
  104. * 1. prime: prime table
  105. * 2. value: the given value for prime factorization (namely, n described above)
  106. *
  107. * Return value:
  108. * Required prime list (namely, {k1, k2, ... , km} described above)
  109. ****************************************************************************************************/
  110. template <typename T>
  111. std::vector<T> factorization(const std::vector<T>& prime, const T& value)
  112. {
  113. std::vector<T> result;
  114.  
  115. T curr = value;
  116. for (size_t i = 0; i < prime.size(); ++i) {
  117. if (prime[i] * prime[i] > curr) { break; }
  118. if ((curr % prime[i]) == 0) {
  119. result.push_back(prime[i]);
  120. while ((curr % prime[i]) == 0) { curr /= prime[i]; }
  121. }
  122. }
  123. if (curr > static_cast<T>(1)) { result.push_back(curr); }
  124.  
  125. return result;
  126. }
  127.  
  128.  
  129. /******************************************************************************************************************
  130. * Given two positive integers n and x, where x = p1 ^ k1 * p2 ^ k2 * ... * pm ^ km, and p1, p2, ... pm are primes,
  131. * this function will return the number of values y that y <= n and gcd(y, x) = 1, where
  132. * gcd(y, x) is the greatest common divisor of y and x.
  133. * Namely, it will find how many values are less than n are coprime with x.
  134. *
  135. * Example: Let n = 12 and x = 6, the result is 4 ({1, 5, 7, 11})
  136. * Note: When n = x, the result is equal to phi(n), where phi is Euler Totient Function.
  137. *
  138. * Parameters:
  139. * 1. prime: prime list {p1, p2, ... , pm}
  140. * 2. value: n
  141. *
  142. * Return value:
  143. * Number of values that are less than n and coprime with x.
  144. ******************************************************************************************************************/
  145. template <typename T>
  146. T coprimeCount(const std::vector<T>& prime, const T value)
  147. {
  148. T ans = 0;
  149.  
  150. // Use Inclusion-Exclusion principle
  151. const T bitmask = (static_cast<T>(1) << prime.size());
  152. for (T bit = 0; bit < bitmask; ++bit) {
  153. T curr = 1, flag = 1;
  154. // Let bit = b1 b2 ... bm, where bit is in [0, 2^ps), ps = prime.size()
  155. // bi = 1, if currently we need to process prime[i]; otherwise skip prime[i]
  156. for (size_t i = 0; i < prime.size(); ++i) {
  157. if ((bit >> i) & 1) { // bi = 1
  158. curr *= prime[i];
  159. flag *= -1;
  160. }
  161. }
  162. // flag = 1 when there is even number of bi = 1
  163. // otherwise, flag = -1
  164. ans += flag * (value / curr);
  165. }
  166.  
  167. // Example: x = 6 = 2 ^1 * 3 ^1
  168. // prime = {2, 3}, and bit will be {00, 01, 10, 11}
  169. // bit = 00: ans += 1 * (value / 1)
  170. // bit = 01: ans += (-1) * (value / 3)
  171. // bit = 10: ans += (-1) * (value / 2)
  172. // bit = 11: ans += 1 * (value / (2 * 3))
  173.  
  174. return ans;
  175. }
  176.  
  177.  
  178. /******************************************************************************************************************
  179. * Given two positive integers n and x, where x = p1 ^ k1 * p2 ^ k2 * ... * pm ^ km, and p1, p2, ... pm are primes,
  180. * this function will return the number of values y that y <= n and gcd(y, x) = 1, where
  181. * gcd(y, x) is the greatest common divisor of y and x.
  182. * Namely, it will find how many values are less than n are coprime with x.
  183. *
  184. * Example: Let n = 12 and x = 6, the result is 4 ({1, 5, 7, 11})
  185. * Note: When n = x, the result is equal to phi(n), where phi is Euler Totient Function.
  186. *
  187. * Parameters:
  188. * 1. prime: prime list {p1, p2, ... , pm}
  189. * 2. value: n
  190. * 3. x: as the x described above
  191. * 4. phi_x: phi(x), where phi is Euler Totient function.
  192. *
  193. * Return value:
  194. * Number of values that are less than n and coprime with x.
  195. ******************************************************************************************************************/
  196. template <typename T>
  197. T coprimeCount(const std::vector<T>& prime, const T value, const T x, const T phi_x)
  198. {
  199. return coprimeCount(prime, value % x) + (value / x) * phi_x;
  200. }
  201.  
  202.  
  203. // return the kth value that is relative prime to p and larger than x
  204. int kthValue(const std::vector<int>& prime, const int x, const int p, int k)
  205. {
  206. #define INF 0x3fffffff
  207.  
  208. const auto ex_prime = factorization(prime, p);
  209. k += coprimeCount(ex_prime, x);
  210.  
  211. int left = 1, right = INF;
  212. // binary search
  213. while (left < right) {
  214. const auto middle = (left + right) / 2;
  215. if (coprimeCount(ex_prime, middle) < k) {
  216. left = middle + 1;
  217. }
  218. else {
  219. right = middle;
  220. }
  221. }
  222.  
  223. return right;
  224. }
  225.  
  226.  
  227. // return the kth value that is relative prime to p and larger than x
  228. int kthValue(const std::vector<int>& prime, const std::vector<int>& phi, const int x, const int p, int k)
  229. {
  230. #define INF 0x3fffffff
  231.  
  232. const auto ex_prime = factorization(prime, p);
  233. k += coprimeCount(ex_prime, x, p, phi[p]);
  234.  
  235. int left = 1, right = INF;
  236. // binary search
  237. while (left < right) {
  238. const auto middle = (left + right) / 2;
  239. if (coprimeCount(ex_prime, middle, p, phi[p]) < k) {
  240. left = middle + 1;
  241. }
  242. else {
  243. right = middle;
  244. }
  245. }
  246.  
  247. return right;
  248. }
  249.  
  250.  
  251. int main(int argc, char *argv[])
  252. {
  253. #define MAX_VALUE 1000000
  254.  
  255. std::vector<int> prime, phi;
  256. const auto prime_count = GeneratePrime(prime, MAX_VALUE);
  257. euler_totient(phi, MAX_VALUE, prime);
  258.  
  259. int t;
  260. while (scanf("%d", &t) == 1) {
  261. for (int i = 0; i < t; ++i) {
  262. int x, p, k;
  263. if (scanf("%d %d %d", &x, &p, &k) == 3) {
  264. printf("%d\n", kthValue(prime, x, p, k));
  265. //printf("%d\n", kthValue(prime, phi, x, p, k)); // much slower...
  266. }
  267. }
  268. }
  269.  
  270. return 0;
  271. }
Add Comment
Please, Sign In to add comment