首页 > 其他分享 >『开摆向』封装万物

『开摆向』封装万物

时间:2024-05-30 21:32:38浏览次数:8  
标签:cnt 封装 struct int return lsqxx ans 开摆 万物

为了节省写数据结构的时间
方便建立多个相同的数据结构,准备把许多数据结构用结构体封装一下来用


链式前向星

namespace lsq {
    typedef int lsqxx;
    struct lq {
        struct lqbz {
            lsqxx v,w,nxt;
        } e[1000005];
        lsqxx h[1000005],cnt;
        inline void add(lsqxx u,lsqxx v,lsqxx w=1) {
            e[++cnt].v=v;
            e[cnt].w=w;
            e[cnt].nxt=h[u];
            h[u]=cnt;
        }
        void erase() {cnt=0;memset(h,0,sizeof(h));return;}
    #define F(z,u) for(int j=z.h[u],v=z.e[j].v,w=z.e[j].w;j;j=z.e[j].nxt,v=z.e[j].v,w=z.e[j].w)
    };
};

使用以下方法建立链式前向星

lq x;

使用以下方法遍历

F(x,u)//x为建立的结构体变量名 u为开始遍历的点
{
	
}

在循环中使用变量 $v$ $w$
获取终点的编号以及边权的值


线段树

线段树基础

struct x_trees{
    struct{
        int l,r,sum,lan;
    }t[2000005];
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;
        if(l==r) return;
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build((k<<1)+1,mid+1,r);
    }
};

区间最大值

继承基础的代码,懒标记还没写,下次补上

struct max_x_trees:public x_trees{
    void add(int k,int x,int y)
    {
        if(t[k].l>x||t[k].r<x) return;
        if(t[k].l==t[k].r)
        {
            t[k].sum=y;
            return;
        }
        add(k<<1,x,y);
        add((k<<1)+1,x,y);
        t[k].sum=max(t[k<<1].sum,t[(k<<1)+1].sum);
    }
    int ask(int k,int x,int y)
    {
        if(t[k].l>y||t[k].r<x) return 0;
        if(t[k].l>=x&&t[k].r<=y) return t[k].sum;
        return max(ask(k<<1,x,y),ask((k<<1)+1,x,y));
    }
};

区间和

继续继承~

struct sum_x_trees:public x_trees{
	void down(int k)
	{
		t[k<<1].lan+=t[k].lan;
		t[k<<1].sum+=(t[k<<1].r-t[k<<1].l+1)*t[k].lan;
		t[(k<<1)+1].lan+=t[k].lan;
		t[(k<<1)+1].sum+=(t[(k<<1)+1].r-t[(k<<1)+1].l+1)*t[k].lan;
		t[k].lan=0;
	}
	void add(int k,int x,int y,int z)
	{
		if(t[k].l>y||t[k].r<x) return;
		if(t[k].l>=x&&t[k].r<=y)
		{
			t[k].sum+=(t[k].r-t[k].l+1)*z;
			t[k].lan+=z;
			return;
		}
		down(k);
		add(k<<1,x,y,z);
		add((k<<1)+1,x,y,z);
		t[k].sum=t[k<<1].sum+t[(k<<1)+1].sum;
	}
	int ask(int k,int x,int y)
	{
		if(t[k].l>y||t[k].r<x) return 0;
		if(t[k].l>=x&&t[k].r<=y) return t[k].sum;
		down(k);
		return ask(k<<1,x,y)+ask((k<<1)+1,x,y);
	}
};

树链剖分


struct cut_tree:public sum_x_trees{
	struct d{
		int num;
		int fa,d,big,siz;
		int xh,top;
	}e[100005];
	int fxh[100005],cntx;
	typedef int lsqxx;
	struct lq {
		struct lqbz {
			lsqxx v,nxt;
		}e[200005];
		lsqxx h[100005],cnt;
		void add(lsqxx u,lsqxx v) {
			e[++cnt].v=v;
			e[cnt].nxt=h[u];
			h[u]=cnt;
		}
#define F(z,u) for(int j=z.h[u],v=z.e[j].v;j;j=z.e[j].nxt,v=z.e[j].v)
	};
	int start[100005];
	void dfs1(int t)
	{
		e[t].siz=1;
		F(q,t)
		{
			if(e[t].fa==v) continue;
			e[v].d=e[t].d+1;
			e[v].fa=t;
			dfs1(v);
			e[t].siz+=e[v].siz;
			if(e[e[t].big].siz<e[v].siz)
				e[t].big=v;
		}
	}
	void dfs2(int t)
	{
		if(!t) return;
		e[t].xh=++cntx;
		trees.add(1,cntx,cntx,e[t].num);
		fxh[cntx]=t;
		if(e[e[t].fa].big==t) e[t].top=e[e[t].fa].top;
		else e[t].top=t;
		dfs2(e[t].big);
		F(q,t)
		{
			if(e[t].fa==v) continue;
			if(e[t].big==v) continue;
			dfs2(v);
		}
	}
	void reset(int n,int root)
	{
		for(int i=1;i<=n;i++)
			e[i].num=start[i];
		e[root].fa=root;
		e[root].d=1;
		dfs1(root);
		dfs2(root);
	}
	void change_line(int x,int y,int z)
	{
		if(e[e[x].top].d<e[e[y].top].d) swap(x,y);
		if(e[e[x].top].d==e[e[y].top].d&&e[x].d<e[y].d) swap(x,y);
		if(e[x].top!=e[y].top)
		{
			trees.add(1,e[e[x].top].xh,e[x].xh,z);
			change_line(e[e[x].top].fa,y,z);
		}
		else
		{
			trees.add(1,e[y].xh,e[x].xh,z);
		}
	}
	int search_line(int x,int y)
	{
		if(e[e[x].top].d<e[e[y].top].d) swap(x,y);
		if(e[e[x].top].d==e[e[y].top].d&&e[x].d<e[y].d) swap(x,y);
		if(e[x].top!=e[y].top)
		{
			return (trees.ask(1,e[e[x].top].xh,e[x].xh)+
				   search_line(e[e[x].top].fa,y));
		}
		else
		{
			return trees.ask(1,e[y].xh,e[x].xh);
		}
	}
	void change_tree(int x,int y)
	{
		trees.add(1,e[x].xh,e[x].siz+e[x].xh-1,y);
	}
	int search_tree(int x)
	{
		return trees.ask(1,e[x].xh,e[x].xh+e[x].siz-1);
	}
};

需要区间和 $sum_x_trees$ 作为前置
需要线段树基础的 $x_trees$ 作为前前置

初始值放入 $start$ 数组
在 $lq$ 中放入边(需调用两次建立双向边)
使用 $reset$ 初始化(包括两个DFS)


二维线段树

基础中的基础


struct double_x_tree{
	struct {
	    int l1,r1,l2,r2;
	    int sum;
	    int lan;
	}t[2000005];
	int _a_[2005][2005];
};

支持矩阵区间和的修改,查询

struct double_add_x_tree{
	void build(int k,int x1,int y1,int x2,int y2)
	{
	    t[k].l1=x1;t[k].r1=y1;
	    t[k].l2=x2;t[k].r2=y2;
	    if(x1==x2&&y1==y2)
	    {
	        t[k].sum=_a_[x1][y1];
	        return;
	    }
	    int midx=x1+x2>>1,midy=y1+y2>>1;
	    if(x1==x2)
	    {
	        build((k<<2)-2+0,x1,y1,x2,midy);
	        build((k<<2)-2+1,x1,midy+1,x2,y2);
	        t[k].sum=t[(k<<2)-2+0].sum+t[(k<<2)-2+1].sum;
	    }
	    else if(y1==y2)
	    {
	        build((k<<2)-2+0,x1,y1,midx,y2);
	        build((k<<2)-2+1,midx+1,y1,x2,y2);
	        t[k].sum=t[(k<<2)-2+0].sum+t[(k<<2)-2+1].sum;
	    }
	    else
	    {
	        build((k<<2)-2+0,x1,y1,midx,midy);
	        build((k<<2)-2+1,midx+1,y1,x2,midy);
	        build((k<<2)-2+2,x1,midy+1,midx,y2);
	        build((k<<2)-2+3,midx+1,midy+1,x2,y2);
	        t[k].sum=t[(k<<2)-2+0].sum+
	                 t[(k<<2)-2+1].sum+
	                 t[(k<<2)-2+2].sum+
	                 t[(k<<2)-2+3].sum;
	    }
	}
	void down(int k)
	{
		t[(k<<2)-2+0].sum+=t[k].lan*(t[(k<<2)-2+0].l2-t[(k<<2)-2+0].l1+1)*(t[(k<<2)-2+0].r2-t[(k<<2)-2+0].r1+1);
		t[(k<<2)-2+1].sum+=t[k].lan*(t[(k<<2)-2+1].l2-t[(k<<2)-2+1].l1+1)*(t[(k<<2)-2+1].r2-t[(k<<2)-2+1].r1+1);
		t[(k<<2)-2+2].sum+=t[k].lan*(t[(k<<2)-2+2].l2-t[(k<<2)-2+2].l1+1)*(t[(k<<2)-2+2].r2-t[(k<<2)-2+2].r1+1);
		t[(k<<2)-2+3].sum+=t[k].lan*(t[(k<<2)-2+3].l2-t[(k<<2)-2+3].l1+1)*(t[(k<<2)-2+3].r2-t[(k<<2)-2+3].r1+1);
		t[(k<<2)-2+0].lan+=t[k].lan;
		t[(k<<2)-2+1].lan+=t[k].lan;
		t[(k<<2)-2+2].lan+=t[k].lan;
		t[(k<<2)-2+3].lan+=t[k].lan;
		t[k].lan=0;
	}
	void add(int k,int x1,int y1,int x2,int y2,int z)
	{
	    if(t[k].l1>x2||t[k].l2<x1||t[k].r1>y2||t[k].r2<y1) return;
	    if(t[k].l1>=x1&&t[k].l2<=x2&&t[k].r1>=y1&&t[k].r2<=y2)
	    {
	        t[k].sum+=z*((t[k].l2-t[k].l1+1)*(t[k].r2-t[k].r1+1));
	    	t[k].lan+=z;
	        return;
	    }
	    down(k);
	    add((k<<2)-2+0,x1,y1,x2,y2,z);
	    add((k<<2)-2+1,x1,y1,x2,y2,z);
	    add((k<<2)-2+2,x1,y1,x2,y2,z);
	    add((k<<2)-2+3,x1,y1,x2,y2,z);
	    t[k].sum=t[(k<<2)-2+0].sum+
	             t[(k<<2)-2+1].sum+
	             t[(k<<2)-2+2].sum+
	             t[(k<<2)-2+3].sum;
	}
	int ask(int k,int x1,int y1,int x2,int y2)
	{
	    if(t[k].l1>x2||t[k].l2<x1||t[k].r1>y2||t[k].r2<y1) return 0;
	    if(t[k].l1>=x1&&t[k].l2<=x2&&t[k].r1>=y1&&t[k].r2<=y2)
	        return t[k].sum;
	    down(k);
	    return ask((k<<2)-2+0,x1,y1,x2,y2)+
	           ask((k<<2)-2+1,x1,y1,x2,y2)+
	           ask((k<<2)-2+2,x1,y1,x2,y2)+
	           ask((k<<2)-2+3,x1,y1,x2,y2);
	}
};

最大流

namespace ISAP{
    int n,m,s,t;
    int cur[100005];
    namespace lsq {
        typedef int lsqxx;
        struct lq {
            struct lqbz {
                lsqxx v,w,nxt;
            } e[1000005];
            lsqxx h[100005],cnt=1;
            inline void add(lsqxx u,lsqxx v,lsqxx w=1) {
                e[++cnt].v=v;
                e[cnt].w=w;
                e[cnt].nxt=h[u];
                h[u]=cnt;
            }
        #define F(z,u) for(int j=cur[u],v=z.e[j].v,w=z.e[j].w;j;j=z.e[j].nxt,v=z.e[j].v,w=z.e[j].w,cur[u]=j)
        }q;
    };using namespace lsq;
    int d[205],gap[205];
    int dfs(int u=s,int in=INT_MAX)
    {
        if(u==t) return in;
        int out=0;
        F(q,u)
        {
            if(d[u]>d[v]&&w)
            {
                int nt=dfs(v,min(w,in));
                in-=nt;out+=nt;
                q.e[j].w-=nt;q.e[j^1].w+=nt;
                if(!in) return out;
            }
        }
        --gap[d[u]];
        if(!gap[d[u]]) d[s]=n+1;
        ++d[u];
        ++gap[d[u]];
        return out;
    }
    int ISAP()
    {
        int ans=0;
        gap[0]=n;
        while(d[s]<n)
            memcpy(cur,q.h,sizeof(q.h)),ans+=dfs();
        return ans;
    }
}
using namespace ISAP;

带有当前弧优化和gas优化


Other

输出数组

#define cs(dt,n,m) \
	for(int i=1;i<=n;i++)\
	{\
		for(int j=1;j<=n;j++)\
			printf("%d ",dt[i][j]);\
		cout<<endl;\
	}

可以输出一个数组矩阵


矩阵

可以实现矩阵加法,矩阵乘法,矩阵快速幂
支持cin cout 读入输出

namespace matrixs{
    #define X 100
    #define Y 100
    typedef long long ll;
    ll matrix_mod=INT_MAX;
    void change_mod(ll x){matrix_mod=x;return;}
    inline ll reads()
    {
        char ch=getchar();int f=1,ans=0;
        for(;!isdigit(ch);ch=getchar()) ch=='-'?f=-1:f=1;
        for(;isdigit(ch);ch=getchar()) ans=(ans<<3)+(ans<<1)+(ch&15);
        return f*ans;
    }
    template<size_t N=X,size_t M=Y>
    struct matrix{
        ll a[N+5][M+5];
        int n=N,m=M;
        matrix(){memset(a,0,sizeof(a));}
        matrix(int x,int y,bool one=0)
        {
            n=x;m=y;memset(a,0,sizeof(a));
            if(one) g(n) a[i][i]=1;
        }
        void read()
        {
            f(i,1,n)
                f(j,1,m)
                    a[i][j]=reads();
        }
        void print()
        {
            ios::sync_with_stdio(false);
            f(i,1,n)
            {
                f(j,1,m) cout<<a[i][j]<<" ";
                cout<<'\n';
            }
            ios::sync_with_stdio(true);
        }
        friend matrix operator +(matrix x,matrix y)
        {
            matrix<> ans(x.n,x.m);
            f(i,1,x.n) f(j,1,x.m)
                ans.a[i][j]=(x.a[i][j]+y.a[i][j])%matrix_mod;
            return ans;
        }
        friend matrix operator *(matrix x,matrix y)
        {
            matrix<> ans(x.n,y.m);
            f(i,1,x.n) f(j,1,y.m) f(k,1,x.m)
                ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j])%matrix_mod;
            return ans;
        }
        friend matrix operator ^(matrix x,ll y)
        {
            matrix<> ans(x.n,x.m,true);
            while(y>0)
            {
                if(y&1) ans=ans*x;
                x=x*x;y>>=1;
            }
            return ans;
        }
    };
    ostream &operator <<(ostream &out,matrix<> &x){x.print();return out;}
    istream &operator >>(istream &in, matrix<> &x){x.read(); return in; }
}using namespace matrixs;

高精度 -by mori

# 商业转载请联系作者获得授权,非商业转载请注明出处。
# For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.
# 协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
# 作者(Author):Mori
# 链接(URL):https://lsoi.top/356.html
# 来源(Source):LSOI-BLOG

#define N 2048
typedef bitset<N> Bint;
bool operator <(const Bint &a,const Bint &b){
   for (int i=a.size()-1;i>=0;--i)
       if (a[i]!=b[i])return a[i]<b[i];
   return 0;
}
bool operator >(const Bint &a,const Bint &b){return b<a;}
bool operator <=(const Bint &a,const Bint &b){return !(b<a);}
bool operator >=(const Bint &a,const Bint &b){return !(a<b);}
Bint operator +(const Bint &a,const Bint &b){return b.any()?(a^b)+((a&b)<<1):a;}
Bint& operator +=(Bint &a,const Bint &b){return a=a+b;}
Bint operator -(const Bint &a){return Bint(1)+~a;}
//Bint operator -(const Bint &a,const Bint &b){return a+(-b);}
Bint operator -(const Bint &a,const Bint &b){return b.any()?(a^b)-((~a&b)<<1):a;}
Bint& operator -=(Bint &a,const Bint &b){return a=a-b;}
Bint operator *(Bint a,Bint b){
   Bint r(0);
   for (;b.any();b>>=1,a<<=1)
       if (b[0])r+=a;
   return r;
}
Bint& operator *=(Bint &a,const Bint &b){return a=a*b;}
pair<Bint,Bint> divide(Bint a,const Bint &b){
   Bint c=0; int i=0;
   while (b<<(i+1)<=a)++i;
   for (;i>=0;--i)
       if (a>=(b<<i))a-=b<<i,c.set(i,1);
   return make_pair(c,a);
}
Bint operator /(const Bint &a,const Bint &b){return divide(a,b).first;}
Bint& operator /=(Bint &a,const Bint &b){return a=a/b;}
Bint operator %(const Bint &a,const Bint &b){return divide(a,b).second;}
Bint& operator %=(Bint &a,const Bint &b){return a=a%b;}
inline void read(Bint &x){
   char ch;int bo=0; x=0;
   for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
   for (;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+(ch-'0'),ch=getchar());
   if (bo)x=-x;
}
inline void print(Bint x){
   vector<Bint> v;
   if (x==0)printf("0");
   for (Bint y=1;y<=x;y*=10)v.push_back(y);
   for (int i=v.size()-1;i>=0;--i){
       int t=0;
       while (x>=(v[i]<<2))x-=v[i]<<2,t+=4;
       while (x>=(v[i]<<1))x-=v[i]<<1,t+=2;
       while (x>=v[i])x-=v[i],++t;
       printf("%d",t);
   }
   printf("\n");
}

01Trie

template<size_t siz=100005,size_t zw=30,size_t minads=0>
class O1tree{
    private:
    struct trees{
        int to[2];
        int cnt;
    }t[siz];
    int cnt=1;
    //ads:如果带负数,权值 +ads
    //w:log2(w) w is 值域
    int ads=minads,w=zw;
    public:
    //插入一个数字
    inline void add(int num)
    {
        num+=ads;
        int u=1;
        ff(i,w,0)
        {
            int v=(num>>i)&1;
            if(!t[u].to[v]) t[u].to[v]=++cnt;
            u=t[u].to[v];
            t[u].cnt++;
        }
    }
    //删除一个数字
    inline void del(int num)
    {
        num+=ads;
        int u=1;
        ff(i,w,0)
        {
            int v=(num>>i)&1;
            u=t[u].to[v];
            t[u].cnt--;
        }
    }
    //查询x这个数的排名
    inline int kth(int num)
    {
        num+=ads;
        int u=1,ans=1;
        ff(i,w,0)
        {
            int v=(num>>i)&1;
            if(v) ans+=t[t[u].to[0]].cnt;
            u=t[u].to[v];
        }
        return ans;
    }
    //查询排名为x的数
    inline int ask(int k)
    {
        int u=1,ans=0;
        ff(i,w,0)
        {
            if(k<=t[t[u].to[0]].cnt)
                u=t[u].to[0];
            else
                k-=t[t[u].to[0]].cnt,
                ans|=(1<<i),
                u=t[u].to[1];
        }
        return ans-ads;
    }
};

笛卡尔树

template<size_t siz=10000005>
struct Dicar_tree{
    struct dicar{
        int l,r;
        int w;
    }t[siz];
    stack<int>s;
    //插入一个节点
    void add(int k,int w)
    {
        t[k].w=w;
        if(s.empty()) {s.push(k);return;}
        while((!s.empty())&&(t[s.top()].w>w))
        {
            t[k].l=s.top();
            s.pop();
        }
        if(!s.empty())
            t[s.top()].r=k;
        s.push(k);
    }
};

蔡勒公式

int getweekday(int YYYY,int MM,int DD)
{
    int a,b,c,d;
    a=YYYY/100;b=YYYY%100;c=MM;d=DD;
    return (a/4-a*2+b+b/4+(13*(c+1))/5+d-1)%7;
}

标签:cnt,封装,struct,int,return,lsqxx,ans,开摆,万物
From: https://www.cnblogs.com/wxh666/p/18223278

相关文章

  • Lua封装函数模块并由其他模块调用
    在Lua中,封装函数通常意味着将一组相关的功能组织在一起,然后通过模块的形式提供给其他脚本调用。Lua的模块可以是简单的脚本文件,也可以是返回一个表的脚本,表中包含了模块的所有公共函数和变量。以下是创建和使用Lua模块的基本步骤:1.创建模块创建一个Lua文件,比如mymodule.lua,并......
  • dotnet封装一个配置工具类
    usingMicrosoft.Extensions.Configuration;namespaceweb.tools;publicclasssettingHelper{publicstaticIConfiguration_config{get;set;}publicsettingHelper(IConfigurationconfiguration){_config=configuration;}//......
  • 封装通用 ECharts 图表组件(三):环形图实现
    在数据可视化领域,ECharts是一个非常流行且功能强大的图表库。它提供了丰富的图表类型,能够满足各种复杂的数据展示需求。在本系列的第三篇文章中,我们将探讨如何封装一个通用的ECharts环形图组件。什么是环形图?环形图是一种特殊的饼图,它由一个内圆和一个外圆组成,中间的部分是......
  • 封装通用 ECharts 图表组件(四):分格柱状图实现
    在数据可视化的世界中,ECharts以其强大的功能和灵活性,成为了开发者们的首选图表库之一。继我们之前探讨的环形图封装之后,本文将带领大家进入另一个实用且美观的图表类型——分格柱状图的封装实现。分格柱状图简介分格柱状图是一种特殊的柱状图,它通过将每个柱子分割成多个小格......
  • js 如何封装一个iframe通讯的sdk
    在JavaScript中,封装一个用于iframe间通信的SDK,可以利用postMessage和message事件监听来实现跨域通信。以下是一个简单的示例,展示如何封装这样一个SDK:步骤1:创建SDK文件首先,创建一个名为IframeCommunicator.js的文件,用于存放你的SDK代码。步骤2:实现SDK逻辑在IframeC......
  • vue3项目中 路由elementPlus当中的标签页结合封装
    在项目当中大家应该都有看到过,像标签页一样的面包屑吧,接下来我为大家介绍一下,主要组成部分:路由+组件库的标签页。ok就这么easy!!!它实现的方法也不难哦请看效果图ok,在中间实现思路与大家分享一下:主要是使用watch监听我们的route路由的变化,然后根据传递过来的路由信息,进行标签页......
  • 干货分享:Vue 3和TypeScript结合进行API封装
    前言:  在现代的前端开发中,使用Vue3和TypeScript结合进行API封装已经成为一种流行的实践。通过将Vue3的响应式性与TypeScript的静态类型检查相结合,我们可以更加安全和高效地管理和使用接口请求。本文将介绍如何在Vue3项目中使用TypeScript进行API封装,以提高代码质量、可......
  • springboot~封装依赖引用包jar还是pom,哪种更规范
    将多个第三方包封装成一个项目后,如果你的目的是让其他开发人员可以直接引用这些依赖,一般来说有两种常见的方式:打成JAR包:将封装好的项目编译打包成JAR文件,其他开发人员可以将这个JAR文件添加到他们的项目中,并在项目的构建工具(比如Maven)中配置该JAR作为依赖。这样做的好处是简单......
  • SD8906A恒定批量降压转换器集成电路IC同步整流器SOT封装
    该SD8906A是一个恒定频率,电流模式PWM降压转换器。该器件集成了一个主开关和一个同步整流器,无需外部肖特基二极管即可实现高效率。它是为单节锂离子(Li+)电池供电的便携式设备的理想选择。输出电压可调低至0.6V。该SD8906A还可以运行在100%的低压差操作占空比,延长便携式系统......
  • SD8002D单声道功率放大器输入1KHZ5V电压驱动功率SOP8封装2.0V-5.5V
    SD8002D是一款AB类,单声道带关断模式,桥式音频功率放大器。在输入1KHz,5V工作电压时,最大驱动功率为:3W,(4Ω负载,总谐波失真<10%),2W,(4Ω负载,总谐波失真<1%);音频范围内总谐波失真噪音小于1%(20赫兹·20KHz);SD8002D应用电路简单,只需要极少数外围器件,就能提供高品质的输出功率。......