zoukankan      html  css  js  c++  java
  • 类欧几里得算法&洛谷P5170题解

    类欧几里得算法&洛谷P5170题解

    好久没更博客了说,不能这样颓废了(flag

    Problem

    给定(n,a,b,c),求(f(a,b,c,n)=sumlimits_{i=0}^nlfloorfrac{ai+b}c floor,g(a,b,c,n)=sumlimits_{i=0}^nlfloorfrac{ai+b}c floor^2,h(a,b,c,n)=sumlimits_{i=0}^nilfloorfrac{ai+b}c floor)

    Algorithm

    先考虑看上去最可做的第一个柿子。

    首先可以通过一些trivial的讨论把(a,b)(c)取模。

    [egin{align} f(a,b,c,n)&=sumlimits_{i=0}^nlfloorfrac{ai+b}c floor\ &=sumlimits_{i=0}^nlfloorfrac{(a\%c)i+b\%c}c floor+frac{(n+1)*n}2lfloorfrac ac floor+(n+1)lfloorfrac bc floor\ &=f(a\%c,b\%c,c,n)+frac{(n+1)*n}2lfloorfrac ac floor+(n+1)lfloorfrac bc floor end{align} ]

    我们接下来考虑(a,b<c)的情况,考虑此时的(lfloorfrac{ai+b}c floor)取值不会超过(n),可以枚举取值。

    [egin{align} f(a,b,c,n) &=sumlimits_{i=0}^nlfloorfrac{ai+b}c floor\ &=sumlimits_{i=0}^nsumlimits_{d=1}^{lfloorfrac{an+b}{c} floor}[lfloorfrac{ai+b}c floorge d]\ 两边大力乘上a^{-1}c &=sumlimits_{i=0}^nsumlimits_{d=1}^{lfloorfrac{an+b}{c} floor}[a^{-1}clfloorfrac{ai+b}c floorge a^{-1}cdgt a^{-1}(cd-1)]\ &=sumlimits_{i=0}^nsumlimits_{d=1}^{lfloorfrac{an+b}{c} floor}[igt frac{(cd-b-1)}a]\ &=sumlimits_{i=0}^nsumlimits_{d=0}^{lfloorfrac{an+b}{c} floor-1}[igt frac{(cd+c-b-1)}a]\ &=sumlimits_{d=0}^{lfloorfrac{an+b}{c} floor-1}(n-lfloorfrac{(cd+c-b-1)}a floor)\ &=nlfloorfrac{an+b}{c} floor-sumlimits_{d=0}^{lfloorfrac{an+b}{c} floor-1}lfloorfrac{(cd+c-b-1)}a floor\ &=nlfloorfrac{an+b}{c} floor-f(c,c-b-1,a,lfloorfrac{an+b}{c} floor-1)\ end{align} ]

    于是我们就可以在(log(n))的渐进时间复杂度下求出(f)

    好的,相信(g,h)不是问题。

    于是我们看看(g)

    [g(a,b,c,n)=sumlimits_{i=0}^nlfloorfrac{ai+b}c floor^2 ]

    套路一波。

    [egin{aligned}g(a,b,c,n)&=sumlimits_{i=0}^n(lfloorfrac{(a\%c)i+b\%c}c floor+ilfloorfrac ac floor+lfloorfrac bc floor)^2\大力展开,上式&=sumlimits_{i=0}^n(lfloorfrac{(a\%c)i+b\%c}c floor^2+i^2lfloorfrac ac floor^2+lfloorfrac bc floor^2+2ilfloorfrac ac floorlfloorfrac{(a\%c)i+b\%c}c floor+2ilfloorfrac bc floorlfloorfrac{(a\%c)i+b\%c}c floor+2ilfloorfrac ac floorlfloorfrac bc floor)^2\设S1(n)&=sumlimits_{i=0}^ni=frac{i*(i+1)}{2},S2(n)=sumlimits_{i=0}^ni^2=frac {i*(i+1)*(2i+1)}6\整理,原式&=g(a\%c,b\%c,c,n)+S2(n)lfloorfrac ac floor^2+(n+1)lfloorfrac bc floor^2+2lfloorfrac ac floor h(a\%c,b\%c,c,n)+2lfloorfrac bc floor f(a\%c,b\%c,c,n)+2S1(n)lfloorfrac ac floorlfloorfrac bc floorend{aligned} ]

    你发现事情变得辣手了起来,我们似乎并不知道这个(h)怎么搞。

    但是你先不管它,假设你知道了(h)怎么算。

    [egin{aligned}g(a,b,c,n)&=sumlimits_{i=0}^nlfloorfrac{ai+b}c floor^2\&=sumlimits_{i=0}^n(2sumlimits_{d=1}^{lfloorfrac{ai+b}c floor}d-lfloorfrac{ai+b}c floor)\&=sumlimits_{i=0}^n(2sumlimits_{d=0}^{lfloorfrac{ai+b}c floor-1}(d+1)-lfloorfrac{ai+b}c floor)\&=2sum_{d=0}^{lfloorfrac {an+b}c floor-1}(d+1)sumlimits_{i=0}^n[lfloorfrac{ai+b}c floorge d+1]-f(a,b,c,n)\&=2sum_{d=0}^{lfloorfrac {an+b}c floor-1}(d+1)(n-lfloorfrac{cd+c-b-1}a floor)-f(a,b,c,n)\&=n*lfloorfrac {an+b}c floor*(lfloorfrac {an+b}c floor+1)-2sum_{d=0}^{lfloorfrac {an+b}c floor-1}(d+1)lfloorfrac{cd+c-b-1}a floor-f(a,b,c,n)\&=n*lfloorfrac {an+b}c floor*(lfloorfrac {an+b}c floor+1)-2h(c,c-b-1,a,lfloorfrac{an+b}c floor-1)-2f(c,c-b-1,a,lfloorfrac{an+b}c floor-1)-f(a,b,c,n)\end{aligned} ]

    我们最后考虑一下(h),首先大力展开

    [egin{aligned}h(a,b,c,n)=S2(n)lfloorfrac ac floor+S1(n)lfloorfrac bc floor+h(a\%c,b\%c,c,n)end{aligned} ]

    好的,继续

    [egin{aligned} h(a,b,c,n)&=sumlimits_{i=0}^nilfloorfrac {ai+b}c floor\ &=sumlimits_{i=0}^nisumlimits_{d=1}^{lfloorfrac{an+b}{c} floor}[a^{-1}clfloorfrac{ai+b}c floorge a^{-1}cdgt a^{-1}(cd-1)]\ &=sumlimits_{i=0}^nisumlimits_{d=0}^{lfloorfrac{an+b}{c} floor-1}[igtfrac{cd+c-b-1}{a}]\ &=S1(n)lfloorfrac {an+b}c floor-sumlimits_{d=0}^{lfloorfrac{an+b}{c} floor-1}sumlimits_{i=0}^ni[frac{cd+c-b-1}age i]\ &=S1(n)lfloorfrac {an+b}c floor-sumlimits_{d=0}^{lfloorfrac{an+b}{c} floor-1}frac{(frac{cd+c-b-1}a)*(frac{cd+c-b-1}a+1)}2\ &=S1(n)lfloorfrac {an+b}c floor-frac12f(c,c-b-1,a,lfloorfrac{an+b}{c} floor-1)-frac12\g(c,c-b-1,a,lfloorfrac{an+b}{c} floor-1) end{aligned} ]

    如此递归,我们就可以在(O(logn))的渐进时间复杂度内把(f,g,h)都求出来了。

    代码

    /*
    @Date    : 2020-02-13 08:16:26
    @Author  : Adscn (adscn@qq.com)
    @Link    : https://www.cnblogs.com/LLCSBlog
    */
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define int ll
    #define IL inline
    #define RG register
    #define gi geti<int>()
    #define gl geti<ll>()
    #define gc getchar()
    #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
    template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
    template<typename T>
    IL T geti()
    {
    	RG T xi=0;
    	RG char ch=gc;
    	bool f=0;
    	while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
    	while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
    	return f?-xi:xi;
    }
    template<typename T>
    IL void pi(T k,char ch=0)
    {
    	if(k<0)k=-k,putchar('-');
    	if(k>=10)pi(k/10);
    	putchar(k%10+'0');
    	if(ch)putchar(ch);
    }
    const int P=998244353,i2=(P+1)>>1;
    inline void exgcd(int a,int b,int &x,int &y){
    	if(!b)return x=1,y=0,void(); 
    	exgcd(b,a%b,y,x);
    	y=(y-a/b*x)%P;
    }
    inline int inv(int a){
    	int x,y;
    	exgcd(a,P,x,y);
    	return (x+P)%P;
    }
    const int i6=inv(6);
    struct data{ll a,b,c;};
    inline data solve(int a,int b,int c,int n)
    {
    	ll n1=(n+1)%P,S1=n1*n%P*i2%P,S2=n*n1%P*(n+n1)%P*i6%P;
    	ll m=(1ll*a*n+b)/c,ac=a/c,bc=b/c,acq=ac*ac%P,bcq=bc*bc%P,nm=n*m%P;
    	if(!a)return (data){n1*bc%P,n1*bcq%P,bc*S1%P};
    	if(a>=c||b>=c){
    		data ret=solve(a%c,b%c,c,n);
    		return (data){
    			(ret.a+S1*ac%P +n1*bc%P)%P,
    			(ret.b
    				+S2*acq%P
    				+n1*bcq%P
    				+2*ac*ret.c%P
    				+2*bc*ret.a%P
    				+2*S1*ac%P*bc%P)%P,
    			(ret.c+S2*ac%P +S1*bc%P)%P};
    	}
    	auto lst=solve(c,c-b-1,a,m-1);
    	data ret;
    	ret.a=(nm-lst.a)%P;
    	ret.b=(nm*(m+1)%P-2ll*(lst.a+lst.c)%P-ret.a)%P;
    	ret.c=(S1*m%P-1ll*i2*(lst.a+lst.b)%P)%P;
    	return ret;
    }
    signed main(void)
    {
    	#ifndef ONLINE_JUDGE
    //	File("");
    	#endif
    	int T=gi;
    	while(T--)
    	{
    		int n=gi,a=gi,b=gi,c=gi;
    		auto ret=solve(a,b,c,n);
    		printf("%lld %lld %lld
    ",(ret.a+P)%P,(ret.b+P)%P,(ret.c+P)%P);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Binary Search Tree Iterator
    Oracle迁移:Linux->Windows
    OCP考点实战演练02-日常维护篇
    Oracle数据库全球化
    Oracle管理磁盘空间和资源
    Oracle数据库资源管理
    使用普通用户替代root来管理IEE
    记录一则ORA-12154,ORA-12560解决过程
    Oracle段收缩功能
    Oracle使用SQL传输表空间
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/12301258.html
Copyright © 2011-2022 走看看