• [P5172] Sum


    “类欧几里得算法”第一题 sum

    【题意】

    给入(n,r),求(sum_{d=1}^n(-1)^{lfloor dsqrt r floor})

    【分析】

    只需要考虑所有(d)中,(lfloor dsqrt r floor)为偶数的个数。显然(lfloor x floor)为偶数(Leftrightarrow lfloor x floor=2 imeslfloorfrac{x}{2} floor)。 那么原式可以改写为:

    [sum_{d=1}^n 1-2 imes(lfloor dsqrt r floormod 2)=sum_{d=1}^n 1-2 imes(lfloor dsqrt r floor-2 imeslfloorfrac{dsqrt r}{2} floor)\ =n-2 imessum_{d=1}^nlfloor dsqrt r floor+4 imessum_{d=1}^nlfloorfrac{dsqrt r}{2} floor ]

    不妨设(f(a,b,c,n)=sum_{d=1}^nlfloor d imesfrac{asqrt r+b}{c} floor),那么原式即为

    [n-2 imes f(1,0,1,n)+4 imes f(1,0,2,n) ]

    考虑关于(f(a,b,c,n))的算法,(开始扣题了),设(k=frac{asqrt r +b}{c})

    (kge1)时,(k)可以拆为一个正数+小于1的非负实数,即

    [f(a,b,c,n)=sum_{d=1}^n lfloor d imes k floor=sum_{d=1}^n d imeslfloor k floor+lfloor d imes(k-lfloor k floor) floor\ =frac{n(n+1)}{2}lfloor k floor+sum_{d=1}^nlfloor d imesfrac{asqrt r+b-lfloor k floor imes c}{c} floor\ =frac{n(n+1)}{2}lfloor k floor+f(a,b-lfloor k floor imes c,c,n) ]

    (k<1)时,(比如上面递归的那层),可以看作是满足

    [egin{cases} 0<xle n\ 0<yle x imes k\ xin Z\ yin Z end{cases} ]

    的点数。考虑再矩形((1,1)(n,lfloor n imes k floor))内容斥可得个数为(n imeslfloor n imes k floor) 减去左上三角的部分,而那部分可当作是(y=x imes k, xin[1,n])的反函数(y=x imes dfrac{1}{k}, xin[1,lfloor n imes k floor])

    其中(dfrac{1}{k}=dfrac{c}{asqrt r+b}=dfrac{c(asqrt r-b)}{(asqrt r+b)(asqrt r-b)}=dfrac{acsqrt r-bc}{a^2r-b^2})

    [f(a,b,c,n)=n imeslfloor n imes k floor-f(ac,-bc,a^2r-b^2,lfloor n imes k floor) ]

    可以发现,情况一二交替递归,且每轮的总的变化与欧几里得算法相似,故知其复杂度为(log​)级的。

    难度海星。。

    然而当(r)为完全平方数时需要单独算,大概会爆LL吧。。

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    LL n,r;
    double x;
    LL f(LL a,LL b,LL c,LL n) {
    	if(!n) return 0;
    	LL d=__gcd(__gcd(a,b),c);
    	a/=d, b/=d, c/=d;
    	double k=(a*x+b)/c;
    	if(k>=1) return n*(n+1)/2*(LL)(k)+f(a,b-(LL)(k)*c,c,n);
    	else return n*(LL)(n*k)-f(a*c,-b*c,a*a*r-b*b,(LL)(n*k));
    }
    int main() {
    	int T;
    	scanf("%d",&T);
    	while(T--) {
    		scanf("%lld%lld",&n,&r);
    		x=sqrt(r);
    		LL c=x;
    		if(c*c==r) {
    			if(c&1) printf("%lld
    ",n-2*((n+1)/2));
    			else printf("%lld
    ",n);
    		} 
    		else printf("%lld
    ",n-2*f(1,0,1,n)+4*f(1,0,2,n));
    	}
    	return 0;
    }
    
  • 相关阅读:
    python while循环语句 结合 if else pass temp语句求触发的余数 的练习题
    IF函数多个条件判断及嵌套
    Python 字符串 加减乘除
    Python条件语句 -- if ,else ( 如果 ,那么)
    input 变量名命名规则
    Python解释器的头部编码用途
    switch留个爪,之后还需要再研究下
    面向对象+JAVA基础
    爱因斯坦台阶
    成功的拆开了SELECT里JOIN个SELECT是啥
  • 原文地址:https://www.cnblogs.com/nosta/p/10299183.html
Copyright © 2020-2023  润新知