BZOJ3817:Sum(类欧几里得)

传送门

题意:

给定正整数 n,r ,求:

d=1n(1)dr

题解:

有点像类欧几里得。

只需要知道:

d=1ndr%2

又因为

x%2=xx22

那么问题转化为求

d=1ndx

显然这是一条从原点出发的直线,要求的是它的下半部分的整数点。

有一个结论是如果这条直线的斜率大于1,那么先减掉1的斜率并加上这个斜率带来的一个直角三角形的贡献,这个新得到的直线覆盖的整点即为原来直线还没有加上的点。

类似于欧几里得,现在我们得到了一个斜率小于1的直线,那么考虑翻转这个坐标系来枚举y轴,发现又变成了一个子问题,这样迭代只会进行 O(logn) 次。

具体的实现由于精度问题,我写的 long double 类并不能通过,所以要用 long long 类做分子分母来表示,记现在直线的斜率为 ax+bc(<1) ,要延伸到长度为 n 的位置。

先计算出在 n 的时候直线可以覆盖的点数 t ,并把 nt 加入贡献中,此时我们多加入了上半部分的三角形,再把这个直线翻转,长度变为 t ,斜率变为 cax+b=c(axb)a2rb2 ,减去这部分的贡献即可,这部分可以递归实现,代码非常的短。

Fastio部分可以忽略掉


#include
typedef long long ll;
typedef long double db;
using namespace std;
const int R_LEN=(1<<18)|1;
struct Fast_io{
    char ibuf[R_LEN],obuf[R_LEN],*s,*t,*wt;
    int buf[50];
    Fast_io(){s=ibuf,t=ibuf; wt=obuf;}
    ~Fast_io(){fwrite(obuf,1,wt-obuf,stdout);}
    inline void print(char c){
        (wt==(obuf+R_LEN)) && (fwrite(obuf,1,R_LEN,stdout),wt=obuf);
        *wt++=c;
    }
    template<typename T>
    inline void W(T x){
        if(x<0){print('-');x=-x;}
        if(!x){print('0');return;}
        while(x){buf[++buf[0]]=x%10;x/=10;}
        while(buf[0])print(buf[buf[0]--]+'0');
    }
    inline char getc(){
        (s==t) && (t=(s=ibuf)+fread(ibuf,1,R_LEN,stdin));
        return (s==t)?-1:*s++;
    }
    inline int rd(){
        char ch=getc(); int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1; ch=getc();}
        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getc();}
        return i*f;
    }
}io;
int T,n,r;db R,mxlen;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll solve(ll a,ll b,ll c,ll len){
    if(!len) return 0;
    ll t=gcd(a,gcd(b,c)); a/=t; b/=t; c/=t;
    t=(a*R+b)/c; ll sum=(len*(len+1)>>1)*t;
    b-=c*t; t=(a*R+b)*len/c;
    return sum+t*len-solve(a*c,-b*c,a*a*r-b*b,t);
}
int main(){
    for(T=io.rd();T;T--){
        n=io.rd(),r=io.rd();
        R=sqrt(r); int t=(int)(R+0.5);
        if(t*t==r){io.W((t&1)?((n&1)?-1:0):n);io.print('\n');continue;}
        int odd_cnt=solve(1,0,1,n);
        odd_cnt-=2*solve(1,0,2,n);
        io.W(n-2*odd_cnt),io.print('\n');
    }
}

你可能感兴趣的:(类欧几里得)