• 类欧几里得算法


    类欧几里得算法

    类欧几里得算法之所以被称为类欧几里得是因为其算法复杂度证明与扩展欧几里得算法类似。

    我认为类欧更偏向于是一种思想。

    其主要思想就是寻找可以简便计算的边界,然后通过化式子将不同情况化为边界递归计算。

    P5170 【模板】类欧几里得算法

    推导

    [f(a,b,c,n)=sum_{i=0}^n lfloorfrac{ai+b}{c} floor ]

    [g(a,b,c,N)=sum_{i=0}^N lfloorfrac{ai+b}{c} floor^2 ]

    [h(a,b,c,N)=sum_{i=0}^N ilfloor frac{ai+b}{c} floor ]

    [f(a,b,c,N)=egin{cases}(N+1)lfloorfrac{b}{c} floor&a=0\frac{N(N+1)}{2}lfloorfrac{a}{c} floor+(N+1)lfloorfrac{b}{c} floor+f(amod c,bmod c,c,N)&age c or bge c\NM-f(c,c-b-1,a,M-1),M=lfloorfrac{aN+b}{c} floor &otherwiseend{cases} ]

    [g(a,b,c,N)=egin{cases}(N+1)lfloorfrac{b}{c} floor^2&a=0\g(amod c,bmod c,c,N)+2lfloorfrac{a}{c} floor h(amod c,bmod c,c,N)+2lfloorfrac{b}{c} floor f(amod c,bmod c,c,N)+frac{N(N+1)(2N+1)}{6}lfloorfrac{a}{c} floor^2+N(N+1)lfloorfrac{a}{c} floorlfloorfrac{b}{c} floor+(N+1)lfloorfrac{b}{c} floor^2&age c or bge c\NM(M+1)-f(a,b,c,N)-2h(c,c-b-1,a,M-1)-2f(c,c-b-1,a,M-1)&otherwiseend{cases} ]

    [h(a,b,c,N)=egin{cases}frac{N(N+1)}{2}lfloorfrac{b}{c} floor&a=0\h(amod c,bmod c,c,N)+frac{N(N+1)(2N+1)}{6}lfloorfrac{a}{c} floor+frac{N(N+1)}{2}lfloorfrac{b}{c} floor&age c or bge c\frac{1}{2}[MN(N+1)-g(c,c-b-1,a,M-1)-f(c,c-b-1,a,M-1)]&otherwiseend{cases} ]

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<tuple>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=x*10+(c^48),c=getchar();
    	return w?-x:x;
    }
    const int mod=998244353;
    tuple<int,int,int> calc(long long a,long long b,long long c,long long n){
    	int f,g,h,fn,gn,hn;
    	if(!a){
    		fn=(n+1)*(b/c)%mod;
    		gn=(n+1)*(b/c)%mod*(b/c)%mod;
    		hn=n*(n+1)%mod*((mod+1)>>1)%mod*(b/c)%mod;
    	}else if(a>=c or b>=c){
    		tie(f,g,h)=calc(a%c,b%c,c,n);
    		fn=(n*(n+1)%mod*((mod+1)>>1)%mod*(a/c)%mod+(n+1)*(b/c)%mod+f)%mod;
    		gn=(n*(n+1)%mod*(2*n+1)%mod*((mod+1)/6)%mod*(a/c)%mod*(a/c)%mod+(n+1)*(b/c)%mod*(b/c)%mod+n*(n+1)%mod*(a/c)%mod*(b/c)%mod+2*(b/c)%mod*f%mod+g+2*(a/c)%mod*h%mod)%mod;
    		hn=(n*(n+1)%mod*(2*n+1)%mod*((mod+1)/6)%mod*(a/c)%mod+n*(n+1)%mod*((mod+1)>>1)%mod*(b/c)%mod+h)%mod;
    	}else{
    		tie(f,g,h)=calc(c,c-b-1,a,(a*n+b)/c-1);
    		fn=(n*((a*n+b)/c)%mod-f+mod)%mod;
    		gn=(n*((a*n+b)/c)%mod*((a*n+b)/c+1)%mod-fn+mod-2*f%mod+mod-2*h%mod+mod)%mod;
    		hn=(n*(n+1)%mod*((a*n+b)/c)%mod*((mod+1)>>1)%mod-f*((mod+1ll)>>1)%mod+mod-g*((mod+1ll)>>1)%mod+mod)%mod;
    	}
    	return tie(fn,gn,hn);
    }
    signed main(){
    	int T=read(),n,a,b,c,f,g,h;
    	while(T--) n=read(),a=read(),b=read(),c=read(),tie(f,g,h)=calc(a,b,c,n),printf("%d %d %d
    ",f,g,h);
    	return 0;
    }
    

    P5171 Earthquake

    题意

    求满足 (ax+by⩽c) 的非负整数解的个数。

    推导

    [y⩽leftlfloorfrac{c-ax}{b} ight floor\ ans=sum_{x=0}^{leftlfloorfrac{c}{a} ight floor}leftlfloorfrac{c-ax}{b} ight floor+1\ =sum_{x=0}^{leftlfloorfrac{c}{a} ight floor}leftlfloorfrac{c+(b-a)x}{b} ight floor-x+1\ (sum_{x=0}^{leftlfloorfrac{c}{a} ight floor}leftlfloorfrac{c+(b-a)x}{b} ight floor)-frac{leftlfloorfrac{c}{a} ight floor(leftlfloorfrac{c}{a} ight floor+1)}{2}+leftlfloorfrac{c}{a} ight floor+1 ]

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #define int long long
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=x*10+(c^48),c=getchar();
    	return w?-x:x;
    }
    long long f(long long a,long long b,long long c,long long n){
    	if(!a) return (n+1)*(b/c);
    	if(a>=c or b>=c) return n*(n+1)/2*(a/c)+(n+1)*(b/c)+f(a%c,b%c,c,n);
    	return n*((a*n+b)/c)-f(c,c-b-1,a,(a*n+b)/c-1);
    }
    signed main(){
    	int a=read(),b=read(),c=read();
    	if(a>b)swap(a,b);
    	printf("%lld
    ",f(b-a,c,b,c/a)-1ll*(c/a)*(c/a+1)/2+c/a+1);
    }
    

    P5172 Sum

    推导

    [ans=sum_{d=1}^n(-1)^{lfloor dsqrt r floor}\=sum_{d=1}^n1-2(lfloor dsqrt r floormod 2)\=sum_{d=1}^n1-2(lfloor dsqrt r floor-2lfloor frac{dsqrt r}2 floor) ]

    [f(a,b,c,n)=sum_{d=1}^nlfloorfrac{asqrt r+b}{c}d floor ]

    (lfloorfrac{asqrt r+b}{c} floorge1) 时,

    [f(a,b,c,n)=sum_{d=1}^nlfloorfrac{asqrt r+b}{c}d floor\=sum_{d=1}^nlfloorfrac{asqrt r+b-clfloorfrac{asqrt r+b}{c} floor}{c}d+lfloorfrac{asqrt r+b}{c} floor d floor\=sum_{d=1}^nf(a,b-clfloorfrac{asqrt r+b}{c} floor,c,n)+frac 1 2n(n+1)lfloorfrac{asqrt r+b}{c} floor ]

    (lfloorfrac{asqrt r+b}{c} floor=0) 时,

    [f(a,b,c,n)=sum_{d=1}^nlfloorfrac{asqrt r+b}{c}d floor\=sum_{d=1}^nsum_{p=1}^{lfloorfrac{asqrt r+b}{c}n floor}[plefrac{asqrt r+b}{c}d]\=sum_{d=1}^nsum_{p=1}^{lfloorfrac{asqrt r+b}{c}n floor}[dgefrac{cp}{asqrt r+b}]\=sum_{p=1}^{lfloorfrac{asqrt r+b}{c}n floor} n-lfloorfrac{cp}{asqrt r+b} floor\ exttt{(无理数,大于等于与大于等价)}\=lfloorfrac{asqrt r+b}{c}n floor n-sum_{p=1}^{lfloorfrac{asqrt r+b}{c}n floor}lfloorfrac{c(asqrt r -b)}{a^2r-b^2}p floor\=lfloorfrac{asqrt r+b}{c}n floor n-f(ac,-bc,a^2r-b^2,lfloorfrac{asqrt r+b}{c}n floor) ]

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

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=x*10+(c^48),c=getchar();
    	return w?-x:x;
    }
    double sr;
    int r;
    long long gcd(long long a,long long b){return b?gcd(b,a%b):a;}
    long long f(long long a,long long b,long long c,long long n){
    	if(!n) return 0;
    	long long g=gcd(gcd(a,b),c);a/=g,b/=g,c/=g;
    	long long k=(a*sr+b)/c;
    	if(k) return f(a,b-c*k,c,n)+n*(n+1)/2*k;
    	return (long long)((a*sr+b)/c*n)*n-f(a*c,-b*c,a*a*r-b*b,(long long)((a*sr+b)/c*n));
    }
    signed main(){
    	int T=read(),n;
    	while(T--){
    		n=read(),r=read();sr=sqrt(r);
    		if((int)sr*(int)sr==r) printf("%d
    ",((int)sr&1)?-(n&1):n);
    		else printf("%lld
    ",n-2*f(1,0,1,n)+4*f(1,0,2,n));
    	}
    	return 0;
    }
    

    P5179 Fraction

    推导

    [f(a,b,p,q,c,d)egin{cases}q=1,p=leftlfloorfrac{a}{c} ight floor+1&leftlfloorfrac{a}{c} ight floor+1⩽leftlceilfrac{c}{d} ight ceil-1\p=1,q=leftlfloorfrac{d}{c} ight floor+1&a=0\ f(b,a,q,p,d,c)&a⩽b and c⩽d\f(amod b,b,p,q,c-leftlfloorfrac{a}{b} ight floor d,d),p=p+leftlfloorfrac{a}{b} ight floor q&age bend{cases} ]

    代码

    #include<cstdio>
    using namespace std;
    void calc(long long a,long long b,long long &p,long long &q,long long c,long long d){
    	if(a/b+1<=(c+d-1)/d-1) p=a/b+1,q=1;
    	else if(!a) p=1,q=d/c+1;
    	else if(a<=b and c<=d) calc(d,c,q,p,b,a);
    	else calc(a%b,b,p,q,c-a/b*d,d),p+=a/b*q;
    }
    signed main(){
    	long long a,b,c,d,p,q;
    	while(~scanf("%lld%lld%lld%lld",&a,&b,&c,&d)) calc(a,b,p,q,c,d),printf("%lld/%lld
    ",p,q);
    	return 0;
    }
    
  • 相关阅读:
    C++学习笔记(十六):友元
    C++学习笔记(十五):异常
    C++学习笔记(十四):模板
    C++学习笔记(十三):类、包和接口
    C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类
    C++学习笔记(十一):void*指针、类型转换和动态内存分配
    C++学习笔记(十):类
    quartz 实现调度任务 SchedulerManager
    Session 活化与钝化 与tomcat钝化驱动器
    web listener
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/14333145.html
Copyright © 2020-2023  润新知