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 }

 

转载于:https://www.cnblogs.com/iamqzh233/p/11027031.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值