zoukankan      html  css  js  c++  java
  • BZOJ3817 Sum(类欧几里得算法)

    设$t=sqrt r$,原题转化为$sum_{x=1}^n(4*lfloorfrac{tx}2 floor-2*lfloor tx floor+1)$
    考虑如何求$sum_{x=1}^nlfloorfrac{bt+c}ax floor$
    开始我写了一个真欧几里得来求直线下整点数目,然后由于里头含小数所以不对。
    于是学习了一下新姿势,思想其实差不多。
    先把a,b,c同时除以gcd(a,b,c),防止爆int。
    之后把斜率变成$frac{bt+c}a-lfloorfrac{bt+c}a floor$,并计算对应贡献。
    第三步把x,y轴互换,这时斜率变成了倒数,即$frac a{bt+c}=frac {abt-ac}{b^2t^2-c^2}$
    特判r是完全平方数的时刻,因为这样直线上会有点,所以减的时候会减多。
    补充:真欧几里得算法:
    $$sum_{0<=x<n} lfloor frac{ax+b}{c} floor=n*lfloor frac{b}{c} floor+frac{n*(n-1)}{2}*lfloor frac{a}{c} floor+sum_{0<=x<lfloor frac{(a\%c)*n+b\%cquad}{c} floor} lfloor frac{cx+(an+b)\%c}{a\%c} floor$$

    #include <cstdio>
    #include <cmath>
     
    int T,n,r;
    double t;
    int gcd(int a,int b) {return b?gcd(b,a%b):a;}
    int sol(int n,int a,int b,int c) {
        if (!n) return 0;
        int tmp=gcd(gcd(a,b),c); a/=tmp; b/=tmp; c/=tmp;
        tmp=(t*b+c)/a; int sum=1ll*n*(n+1)*tmp>>1;
        c-=tmp*a; tmp=(t*b+c)*n/a;
        return sum+n*tmp-sol(tmp,b*b*r-c*c,a*b,-a*c);
    }
     
    int main() {
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d",&n,&r),t=sqrt(r);
            if((int)t==t) printf("%d
    ",(r&1)?((n&1)?-1:0):n);
            else printf("%d
    ",n+4*sol(n,2,1,0)-2*sol(n,1,1,0));
        }
        return 0;
    }
  • 相关阅读:
    SQL SERVER备份数据库存储过程.
    JMail组件使用中文文档
    Oracle,SQL Server,Access万能数据库通用类!
    快速幂的理解及使用
    关于地图坐标问题转换
    ref和依赖注入
    Unity3D 中的程序后台运行
    Unity中创建双面材质
    Unity3d 移动平台中文显示问题
    Unity3D 4.0中使用传统动画
  • 原文地址:https://www.cnblogs.com/juruolty/p/6918526.html
Copyright © 2011-2022 走看看