codeforces 1182F: Maximum Sine

题意大概就是要求$2p \mod 2q$距离$q$最近。

为了方便,我们把$p$和$q$同时乘2

我们可以二分一个$y$。

那么就是询问$px \mod q$在$[\frac{q}{2}-y,\frac{q}{2}+y]$上是否有取值。

令$l=\frac{q}{2}-y,r=\frac{q}{2}+y$

等价于询问$\sum_{x=a}^{b} \lfloor \frac{px+q-l}{q} \rfloor - \lfloor \frac{px+q-r-1}{q} \rfloor$是否大于0

使用类欧即可解决。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 inline LL Euc(LL n, int a, int b, int c) {
 5     if(n == -1) return 0;
 6     if(a == 0) return 1ll * (b / c) * (n + 1);
 7     if(a >= c || b >= c) {
 8         return 1ll * n * (n + 1) / 2 * (a / c) + 1ll * (n + 1) * (b / c) + Euc(n, a % c, b % c, c);
 9     }
10     LL m = (1ll * a * n + b) / c;
11     return 1ll * n * m - Euc(m - 1, c, c - b - 1, a);
12 }
13 inline LL get_ab(int A, int B, int a, int b, int c) {
14     return Euc(B, a, b, c) - Euc(A - 1, a, b, c);
15 }
16 inline bool check(int a, int b, int p, int q, int mid) {
17     int l = q / 2 - mid, r = q / 2 + mid;
18     LL res = get_ab(a, b, p, q - l, q) - get_ab(a, b, p, q - r - 1, q);
19     if(res) return true;
20     return false;
21 }
22 inline void exgcd(int p, int q, LL &x, LL &y) {
23     if(q == 0) {
24         x = 1, y = 0;
25         return;
26     }
27     exgcd(q, p % q, y, x);
28     y -= 1ll * (p / q) * x;
29 }
30 inline LL Do(int p, int q, int a, int b, int t) {
31     int GCD = __gcd(p, q);
32     if(t % GCD != 0) return 1e18;
33     p /= GCD, q /= GCD, t /= GCD;
34     LL x, y;
35     exgcd(p, q, x, y);
36     x *= t, y *= t;
37     x += 1ll * (a - x) / q * q;
38     while(x < a) x += q;
39     while(x - q >= a) x -= q;
40     if(x > b) return 1e18;
41     return x; 
42 }
43 inline void solve() {
44     int a, b, p, q;
45     scanf("%d%d%d%d", &a, &b, &p, &q);
46     p *= 2; q *= 2;
47     int l = 0, r = q / 2, t = 0;
48     while(l <= r) {
49         int mid = (l + r) / 2;
50         if(check(a, b, p, q, mid)) r = (t = mid) - 1;
51         else l = mid + 1;
52     }
53     printf("%lld\n", min(Do(p, q, a, b, q / 2 - t), Do(p, q, a, b, q / 2 + t)));
54 }
55 int main() {
56     int T;
57     scanf("%d", &T);
58     while(T --) {
59         solve();
60     }
61 }

 

posted @ 2019-06-15 11:36  iamunstoppable  阅读(368)  评论(0编辑  收藏  举报