zoukankan      html  css  js  c++  java
  • CF1182F Maximum Sine【类欧,扩欧】

    题目链接:洛谷

    题目描述:求整数$xin [a,b]$使得$|2px mod 2q-q|$最小,如果有多个$x$输出最小的。

    数据范围:$1leq a,b,p,qleq 10^9$


    第一道类欧的不是模板的题??

    首先一看就尝试一下二分,如何判断$2px mod 2q in [l,r]$呢?我们发现

    $$[2px mod 2q in [l,r]]=lfloorfrac{2px-l}{2q} floor-lfloorfrac{2px-r-1}{2q} floor$$

    所以存在$xin [a,b]$使得$2px mod 2q in [l,r]$,只需要判断$sum_{x=a}^b(lfloorfrac{2px-l}{2q} floor-lfloorfrac{2px-r-1}{2q} floor)$是否大于0就可以了,这个使用类欧计算。

    找到最小的偏差值$l$之后可以使用扩欧解同余方程。时间复杂度$O(log^2 n)$。

     1 #include<bits/stdc++.h>
     2 #define Rint register int
     3 using namespace std;
     4 typedef long long LL;
     5 LL t, a, b, p, q, len;
     6 inline LL calc(LL a, LL b, LL c, LL n){
     7     if(!a || !n) return (n + 1) * (b / c);
     8     if(n < 0) return 0;
     9     LL m = (a * n + b) / c;
    10     if(a >= c || b >= c) return calc(a % c, b % c, c, n) + (n * (n + 1) >> 1) * (a / c) + (n + 1) * (b / c);
    11     return m * n - calc(c, c - b - 1, a, m - 1);
    12 }
    13 inline LL exgcd(LL a, LL b, LL &x, LL &y){
    14     if(!b){x = 1; y = 0; return a;}
    15     LL gcd = exgcd(b, a % b, y, x);
    16     y -= a / b * x;
    17     return gcd;
    18 }
    19 int main(){
    20     scanf("%lld", &t);
    21     while(t --){
    22         scanf("%lld%lld%lld%lld", &a, &b, &p, &q);
    23         LL l = 0, r = q, mid, P = p << 1, Q = q << 1;
    24         while(l < r){
    25             mid = l + r >> 1;
    26             LL L = q - mid, R = q + mid + 1;
    27             if(calc(P, Q - L, Q, b) + calc(P, Q - R, Q, a - 1) - calc(P, Q - L, Q, a - 1) - calc(P, Q - R, Q, b) > 0) r = mid;
    28             else l = mid + 1;
    29         }
    30         LL x, y, gcd = exgcd(P, Q, x, y), ans = 1e9; P /= gcd; Q /= gcd;
    31         if((q - l) % gcd == 0){
    32             LL xx = (q - l) / gcd * x; xx += (a - xx) / Q * Q;
    33             while(xx >= a) xx -= Q; while(xx < a) xx += Q;
    34             ans = min(ans, xx);
    35         }
    36         if((q + l) % gcd == 0){
    37             LL xx = (q + l) / gcd * x; xx += (a - xx) / Q * Q;
    38             while(xx >= a) xx -= Q; while(xx < a) xx += Q;
    39             ans = min(ans, xx);
    40         }
    41         printf("%lld
    ", ans);
    42     }
    43 }
    CF1182F

    后来看了一波官方题解,结果发现是一个类似BSGS的分块,时间复杂度$O(sqrt{n})$。(写得不好还要带一个log...)

    (还是上面那个方法更好一些)

    (最主要是看起来更高大上一点。。。)

  • 相关阅读:
    centos7 mysql 数据库备份与还原
    Centos 7 搭建wordpress
    Centos 7 安装 mysql5.7
    linux 搭建php网站许愿墙
    GNOME桌面的安装
    cetnos 7 ntp服务的安装与配置
    Tornado初探
    Mysql报错 Cannot load from mysql.proc
    zabbix install
    PYPY_GC
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/11108875.html
Copyright © 2011-2022 走看看