数论从白痴到入门

数论

概念基础

注:本文默认 n/d 为下取整的除法。

整除

定义:对于两个数 a,b ,我们称 a|b ,当且仅当存在一个 k 使得 b=ak

这个运算有一些稍微值得被称为性质的性质,如下:

性质1

该运算具有传递性,即 a|bb|c 时,a|c 成立。

好像也没什么好说的性质了。

然后对于 a|b 的情况下,a 称为 b 的约数, b 称为 a 的倍数。

实际上所有数之间的关系可以用 b=ak+c (0c<a) 表示,当 c=0 时,a|b 成立。 其中 c 称为余数。

最大公约数和最小公倍数

最大公约数(gcd)和 最小公倍数(lcm) :字面意思,不多说了。

gcd(a,b)=1 ,那么我们称 a,b 互素。(多于两个数的情况也有这样类似的定义)

需要注意,多个数互素不一定他们两两互素。

求解gcd

如果求解 a,bgcd(a,b) ?

不妨钦定 a>ba|b 的情况答案直接是 a ,不考虑了,我们只考虑 ab 的情况。

我们证明 gcd(a,b)=gcd(b,a%b) 成立即可,证明如下:

a=bk+c ,显然有 c=a%b 。我们取 d 满足 d|a,d|b ,显然 da,b 公约数。

现在我们证明 d|cc=abk ,那么 c/d=a/dbk/d ,显然 c/d 为整数,那么 d|c 。这是必要性。

充分性同理不再赘述。

所以 gcd(a,b)=gcd(b,a%b) 成立。Q.E.D.

那么之后递归求解即可。当 a%b=0 时,此时的 b 就是最大公因数。(因为是找到的第一个整除的)

复杂度 O(logn) 的。因为每次取模会至少让数折半。

code
int gcd(int x,int y){
    if(!x) return y;
    return gcd(y%x,x);
}
求解lcm

对于 a,b 质因数分解得到,a=i=1npici,b=i=1nqidi

显然 lcm(a,b)=i=1npimax{ci,di}gcd(a,b)=i=1npimin{ci,di}

由于 ci+di=max{ci,di}+min{ci,di}

那么 gcd(a,b)lcm(a,b)=ab ,可以通过算 gcd(a,b) 求解。

质数

没有除 1 和它本身以外的因数的数叫做质数。

性质1

一个合数 n 一定存在素数 pn 使得 pn

首先合数可以质因数分解且至少有两个质因数,那么结论显然。

性质2

所以大于 3 的质数都可以写成 6n±1

发现 6n+2,6n+3,6n+4 都不行即可得证。

素数的筛取 欧拉筛

算数基本定理和引理

算数基本引理

素数 p|ab 时,p|ap|b 至少成立一个。

质因数分解证明。

算数基本定理

对于正整数 a ,其存在唯一的质因数分解。

证明略证,不为质因数的可以拆成质因数。

同余

ab (mod n) ,字面意思。这样的我们称 ab 同余。这个式子称为同余式。

性质1

具有传递性。简单不证。

性质2

具有线性性和积性。即对于 a,b,c,dZ,nNa,b 同余, c,d 同余,那么:

a+cb+d (mod n)a×cb×d (mod n)

转成余数大家就都一样了,得证。

性质3

对于 a,bZ,k,mNab (mod m) ,那么 akbk (mod mk)

以及当 d|a,d|b,d|m 时,a/db/d (mod m/d) 成立。

证明:

a=x1m+c1,b=x2m+c2,那么上述式子只需代入后结论显然。

性质4

对于 a,bZ,d,mN,d|mab (mod m) ,那么 ab (mod d)

证明:

a=x1m+c1,b=x2m+c2,由于 dma%d=b%d=c1=c2

Q.E.D.

同余的乘法逆元

然后同余存在乘法逆元的概念。ax1(mod b),则 x=a1 ,称为 a 的乘法逆元。

逆元的代码

逆元递推式子证明

首先 111(mod p) 显然。

考虑当前求 i 的逆元。设 k=p/i,j=p%i ,有 p=ki+j ,那么 ki+j0(mod p)

ki+j0i1kj1i1(p/i)(p%i)1i1p(p/i)(p%i)1

直接递推即可。

其实我们通过上式中 (p 这个部分还可以发现只有当 ip 时,imod p 意义下才存在逆元。

然后关于另外那些东西为什么正确,我们之后证明。

同余方程

形如 axc(mod b) 的方程叫做同余方程。

扩展欧几里得

求解 ax+by=gcd(a,b) 的算法。

令:

ax1+by1=gcd(a,b)bx2+(a%b)y2=gcd(b,a%b)

则:

ax1+by1=bx2+(a%b)y2ax1+by1=bx2+(a((a/b)×b) )y2 ax1+by1=ay2+b(x2(a/b)y2)

于是有 x1=y2,y1=x2(a/b)y2

递归求解即可。设置 x=1,y=0 返回递归。

根据一些写法不同,有些细节也不太一样,请注意。

code
int exgcd(int a,int b,int &x,int &y){
    if(!a){
        x=0;y=1;
        return b;
    }
    int d=exgcd(b%a,a,x,y);
    int tmp=y;
    y=x;x=tmp-(b/a)*x;
    return d;
}

模板题 参考代码:(去除了头文件)

int exgcd(int a,int b,int &x,int &y){
    if(!a){
        x=0;y=1;
        return b;
    }
    int d=exgcd(b%a,a,x,y);
    int tmp=y;
    y=x;x=tmp-(b/a)*x;
    return d;
}
inline bool LiEu(int a,int b,int c,int &x,int &y){
    int d=exgcd(a,b,x,y);
    if(c%d) return 0;
    int k=c/d;
    x*=k;y*=k;
    return d;
}
int main(){
    filein(a);fileot(a);
    int a,b,c=1,x,y;    
    read(a,b);
    if(int d=CgEu(a,b,c,x,y) ){
        int t=b/d;
        printf("%d\n",(x%t+t)%t);
    }
    return 0;
}
定理1(裴蜀定理)

gcd(a,b)c 为方程 ax+by=caxc(mod b) 有整数解的充要条件。

或者对于正整数 a,b ,存在 x,y 使得 ax+by=gcd(a,b)

证明:

充分性:

k 为最小的非负数满足 ax+by=k,令 q=(a/k)

r=a%k=aqk=aq(ax+by)=a(1qx)+b(qy)

所以 r 满足 ax+by=r ,且 r[0,k]

由于 k 是满足 ax+by=k 的最小的正数,有 r=0 ,即 k|a

同理可得 k|b

d=gcd(a,b) ,有 k|dkd

又因为 d|a,d|b ,且 k=ax+by ,得 d|k

所以 d=k

所以 ax+by=cc 的最小非负取值为 gcd(a,b)

显然对于 kgcd(a,b),kZ+ 都满足 ax+by=kgcd(a,b)

Q.E.D.

必要性:

d=gcd(a,b)

ax+by=c 有解,d|ax,d|by ,则 d|(ax+by),即 d|c

Q.E.D.

扩展: 对于关于 x 的不定方程 i=1nxiyi=c ,其有解的充要条件是 gcd{xi}|c

知道就好,不证了。

我们知道了这个东西,就可以对于方程 ax+by=c ,先求出 x0,y0 满足 ax0+by0=gcd(a,b) ,那么根据倍数关系直接可以得到一组解 x1=cgcd(a,b)x0,y1=cgcd(a,b)y0

然后我们发现对于 x1,y1 ,可知方程的其他解都形如 x=x1+bt,y=y1at,于是方程所有解都可以求得。

然后 x%t,t=bgcd(a,b) 就是最小正整数解。

数论函数

我们在之前已经稍微提过了,这里不再赘述。

莫比乌斯反演及数论函数基本概念

莫比乌斯反演

筛法

欧拉筛

杜教筛

欧拉函数

定义 φ(n) ,表示小于等于 n 的数中与 n 互质的数的个数。

一个显而易见的结论,当 n 为质数的时候,φ(n)=n1

性质1

欧拉函数是积性函数。

结论在 欧拉筛 已经证明。

性质2

1φ(n)=id(n)

证明:

由于函数积性性,所以我们只考虑 n=pc 的情况即可。(p 是质数)

1φ(n)=d|nφ(nd)=i=0cφ(pi)=1+p0(p1)+p1(p1)+...+pc1(p1)=pc=id(n)

Q.E.D.

性质3

n=i=1cpiki,有 φ(n)=ni=1cpi1pi

证明:

φ(n)=i=1cφ(piki)=i=1c(pi1)×piki1=i=1cpi1pi×piki=ni=1c(11pi)

Q.E.D.

威尔逊定理(Wilson)

威尔逊定理

对于素数 p(p1)!1(mod p)

证明这个定理前先证明几个结论。

引理1

对于素数 p 和集合 S={2,3,4,...,p2} 中的元素 a, 一定存在 bSab,ba1(mod p)

证明:

反证。

如果 b=1,且 ab1(mod p) ,则 a 必定为 1,矛盾。

如果 b=p1 ,则 a(p1)1(mod p) ,然后有 a1(mod p) ,则 a 必为 p1,矛盾。

因此结论成立。

Q.E.D.

引理2

对于元素 aAA,p 定义同上),他们模 p 意义下的逆元互不相同。

证明:

反证。假设存在两个不同的 a 的逆元 a1,a2 ,那么a1a=a2a=1(mod p) ,则 (a1a2)a0(mod p),因此 a1=a2 ,矛盾。

因此结论成立。

Q.E.D.

接下来证明威尔逊定理。

证明:由引理1,可知 (p1)!1×(p1)(mod p)

得证 (p1)!p1(mod p)

Q.E.D.

费马小定理和欧拉定理

费马小定理

p 为素数,则 apa(mod p) ,如果 gcd(a,p)=1 ,还有 ap11(mod p)

证明:

我们任取一个正整数 aa 不为 p 的倍数。

可以发现 (p1)!i=1p1(i×a)(mod p),因为 i×a%p 是互不相同的(相当于增减 a ,但是由于不整除,余数上固定增减一个小于 p 的数,又由于模数是素数没有约数必然会错位,所以可知)。

(p1)!ap1×(p1)!(mod p)

ap11(mod p)

gcd(a,p)=1 不成立时,那个 1 无法取的,只能得到 apa(mod p)

欧拉定理

gcd(a,m)=1 ,则 aφ(m)1(mod m) (注意这里区别在于不需要要求 m 是素数)

证明:

构造一个与 m 互质的数列,那么证明就和费马小定理的差不多了。

n=φ(m)

r1,r2,...,rn 为一个 m 的简化剩余系,那么 ar1,ar2,...arn 也是一个 m 的简化剩余系。

然后有 r1r2...rnanr1r2...rn(mod m) ,于是 aφ(m)1(mod m)

Q.E.D.

发现费马小定理就是其中一个特殊情况。

扩展欧拉定理

ab={ab%φ(m),gcd(a,m)=1ab,gcd(a,m)1,b<φ(m)ab%φ(m)+φ(m),bφ(m) (mod m)

不证啦!想了解的可以看 OI_wiki

中国剩余定理

中国剩余定理

求解一元线性同余方程:

{xa1(mod n1)xa2(mod n2)xak(mod nk)

其中 n1,n2,...,nk 要求互质。

我们提出一种古人的做法,然后证明其正确性并加以理解。

  1. 计算 n=ni
  2. 对于第 i 个方程计算 mi=nni
  3. 对于第 i 个方程计算 mi1 (在模 ni 意义下)
  4. 对于第 i 个方程计算 ci=mimi1
  5. 得出方程唯一解 x=i=1kaici(mod n)

证明一下这个式子的正确性。

证明:

下面的证明中,第二步的理由是 ni|n ,第三步的理由是对于 jimj%ni=0

xj=1kajcj(mod n)xj=1kajcj(mod ni)xaici(mod ni)xaimi(mi1%ni)(mod ni)xai(mod ni)

Q.E.D.

code
inline ll CRT(){
    ll P=1;
    for(int i=1;i<=n;++i) P*=p[i];
    for(int i=1;i<=n;++i){
        ll zm=P/p[i],fm,y;
        LiEu(zm,p[i],1,fm,y);
        ans=(ans+1ll*a[i]*zm%P*fm%P)%P;
    }
    return ans;
}
扩展中国剩余定理

其实我感觉这个东西和上面的东西没有什么关系了。

先考虑只有两个方程 xa1(mod m1),xa2(mod m2) 的情况。

得到不定方程 x=m1p+a1=m2q+a2,即 m1pm2q=a2a1

于是可以 exgcd 求解出一组解 p0,q0 。(当然无解也是可能的)

由于 x=m1p+a1=m2q+a2,然后我们构造同余方程 xm1p+a1(mod lcm(m1,m2) )

现在我们证明方程的通解是对于其中一个解 x0 来说的,有通解 x=x0+klcm(m1,m2)

证明:

等价于证明 0,1,2,...,lcm(m1,m2) 之中只有一个解。

那么我们假设其中有两个解 x,ylcm(m1,m2),xy ,那么他们都满足给出的两个方程,相互作差可以发现 xy 满足 (xy)%m1=0(xy)%m2=0 ,即 lcm(m1,m2)(xy)

由于 x,ylcm(m1,m2) ,只有当 (xy)=0 ,即 x=y 时成立。

那么可知每个模 lcm(m1,m2) 的完全剩余系中只有一组解。

Q.E.D.

因此可得同余方程 xm1p+a1(mod lcm(m1,m2) ),多个方程接着以这种方式合并即可。

inline ll mul_low(ll a,ll b,ll p){
    ll res=0;bool f=0;
    if(b<0) {b=-b;f=1;}
    while(b){
        if(b&1) res=(res+a+p)%p;
        a=(a+a+p)%p;
        b>>=1;
    }
    return f?-res:res;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!a){
        x=0;y=1;
        return b;
    }
    ll d=exgcd(b%a,a,x,y);
    ll tmp=y;
    y=x;x=tmp-(b/a)*x;
    return d;
}
inline bool LiEu(ll a,ll b,ll c,ll &x,ll &y){
    ll d=exgcd(a,b,x,y);
    if(c%d) return 0;
    ll k=c/d,t=b/d;
    x=mul_low(x,k,t);
    return 1;
}
ll a1,a2,m1,m2;
ll gcd(ll a,ll b){
    if(!a) return b;
    return gcd(b%a,a);
}
inline ll lcm(ll a,ll b){
    return (a/gcd(a,b) )*b;
}
int n;
int main(){
    filein(a);fileot(a);
    read(n);
    read(m1,a1);
    for(int i=2;i<=n;++i){
        read(m2,a2);
        ll p,q;
        LiEu(m1,m2,a2-a1,p,q);
        ll new_m=lcm(m1,m2);
        a1=(mul_low(p,m1,new_m)+a1)%new_m;
        m1=new_m;
    }
    printf("%lld\n",a1);
    return 0;
}

卢卡斯定理(Lucas)

卢卡斯定理

对于质数 p ,有:

(nm)%p=(n/pm/p)(n%pm%p)%p

证明:

发现 (pn)%p ,只有在 n=0n=p 的情况下,有 p(pn)

那么有 (pn)=[n=0n=p]

于是:

(a+b)pi=0p(pi)aibpii=0p[i=0i=p]aibpiap+bp(mod p)

我们由

(1+x)ni=0n(ni)xi1ni

可知,(nm) 是在第 xm 项的取值。

又由我们前面证明的东西:

(1+x)n(1+x)p(n/p)(1+x)n%p(1+xp)n/p(1+x)n%p

然后我们观察第 xm 项:

(nm)xm(n/pm/p)xp(m/p)(n%pm%p)xm%p(n/pm/p)(n%pm%p)xm(nm)(n/pm/p)(n%pm%p)(mod p)

可以这么构造的原因是 p(m/p) 必定要是 p 的倍数,且 n%pp1 ,所以有且仅有这种构造满足次数和为 m

一个另外的对该公式的理解是 nmp 进制下的每位的组合数的乘积,可以用于一些奇怪的地方。

同余最短路

大多是两种类型的题目:

  1. 用很多数拼凑一个大数,问是否可以拼成。
  2. 给一些数的变换操作(有模数限制),问到达的最少步数。

其中第一个本质上是以一个小数作为模数,展开剩余系,然后对于剩余系上每个数存储最低可以到达的与当前数同余的数,比这个数大或等于就可以到达(因为剩余系的模数是可以用来拼数的),否则到达不了。

第二个本质就是最短路,不过由于模数限制会反复到达一些点。

这个部分不那么需要证明的思想,更多用到的是一种图论感觉的思想。

讲两道典型例题:

跳楼机

题意还是挺简单的,就不再简化了。

本质上就是给了三个数 x,y,z ,问 h 及之下有多少可以被拼凑出来。

我们取这个三个数的最小值最为模数展开剩余系,然后形如 +k 边权为 k 的边,跑最短路可以得到最低可达。然后计算一下即可。

Small Multiple

题意还是简单,不简化了。

转换一下,对给出的数展开剩余系,可以转换成两种操作:×10+1

可以发现每次 +1 都使得数位累加 +1 。我们将这两种操作视作两条边,然后 ×10 边权为 0+1 边权为 1 ,然后从 10 跑最短路。

你可能发现连续 +1 到进位的情况是不正确的,但是不用担心,这种操作肯定是不优的,因此不会对答案造成影响。

由于最坏一直 +1 都能到达,复杂度 O(n)

大概就是这样的东西吧。

原根

此文

二次剩余

如果存在 x2a(modp) ,则称 x 为模 p 的二次剩余。

通俗来说就是开平方。需要注意的是,x 不需要小于 p

先声明 Legendre 记号:

(xp)={1,p|xx为模p的二次剩余1,p|xx不为模p的二次剩余0,p|x

Euler 叛别准则

若奇素数 p 满足 p|a,则:

ap12(xp)

证明略。对于 p 的原根 gka(modp),此时若 k 为偶数,二次剩余的条件得到满足。

Legendre 记号为完全积性函数。

小于 p 的正数中二次剩余的数量与非二次剩余数量相等。

但是这个只能判断是否为二次剩余,我们考虑怎么给这玩意开根。

Cipolla算法

【模板】二次剩余

考虑求 x2n(modp)

Euler判别准则 判无解,再特判 0

如果有解则随意选一个数 a 开始。这个 a 需要满足,a2n 为非二次剩余。

这个 a 我们随机算取,由上面的内容我们知道概率为 12

然后设 i2=(a2n) ,然后答案就为 ±(a+i)p+12。这个 i 我们视作虚数,因为实际上 a2n 是非二次剩余,这个 i 实际上并不存在实际的意义。

因为我们知道:

(a+i)p+1=(ap+ip)(a+i)=(a+i)(ai)=c

第三步的理由是 ip=ip1i=(a2n)p12i=i ,由 Euler判别准则

然后直接算就没了。

#include<bits/stdc++.h>
#define ll long long
#define db double
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define sky fflush(stdout)
#define gc getchar
#define pc putchar
namespace IO{
	template<class T>
	inline void read(T &s){
		s=0;char ch=gc();bool f=0;
		while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
		while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
		if(ch=='.'){
			T p=0.1;ch=gc();
			while('0'<=ch&&ch<='9') {s=s+p*(ch^48);p/=10;ch=gc();}
		}
		s=f?-s:s;
	}
	template<class T,class ...A>
	inline void read(T &s,A &...a){
		read(s);read(a...);
	}
};
using IO::read;
int n,mods;
inline int inc(int x,int y){
	return (x+=y)>=mods?x-mods:x;
}
inline int dec(int x,int y){
	return (x-=y)<0?x+mods:x;
}
inline int mul(int x,int y){
	return 1ll*x*y%mods;
}
inline int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}
int I2;
struct Complex{
	int a,b;
	inline friend Complex operator * (Complex x,Complex y){
		return {inc(mul(x.a,y.a),mul(mul(x.b,y.b),I2) ),inc(mul(x.a,y.b),mul(x.b,y.a) )};
	}
};
inline Complex qpow(Complex a,int b){
	Complex ans={1,0};
	while(b){
		if(b&1) ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}
std::mt19937 rd(time(0)*114+clock()*514);
inline void solve(){
	read(n,mods);
	if(n==0){
		printf("%d\n",0);
		return;
	}
	if(qpow(n,(mods-1)/2)==mods-1){
		printf("Hola!\n");
		return;
	}
	while(1){
		int a=(rd()%(mods-1) )+1;
		I2=dec(mul(a,a),n);
		if(qpow(I2,(mods-1)/2)==mods-1){
			Complex ans={a,1};
			ans=qpow(ans,(mods+1)/2);
			int ans1=ans.a,ans2=inc(-ans.a,mods);
			if(ans1>ans2) std::swap(ans1,ans2);
			printf("%d %d\n",ans1,ans2);
			break;
		}
	}
}
int main(){
	file(a);
	int T;read(T);
	while(T--){
		solve();
	}
	return 0;
}

离散对数

BSGS

可爱的质数/【模板】BSGS

解关于 x 的同余方程 axn(modp)

考虑到 p 为质数,由于 ax=axmod(p1),我们可以考虑分块,块长根号。

于是 x 可以表示为 x×B+y。预处理出 {ax|x[0,B1]} ,然后 axn 一起加入 hash表。然后预处理出 ai×B 然后依次查表即可。

其实你也可以写成减的形式,就不需要求逆元。

因为我们要求的是:

ax×Bnay(modp)

#include<bits/stdc++.h>
#define ll long long
#define db double
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define sky fflush(stdout)
#define gc getchar
#define pc putchar
namespace IO{
	template<class T>
	inline void read(T &s){
		s=0;char ch=gc();bool f=0;
		while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
		while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
		if(ch=='.'){
			T p=0.1;ch=gc();
			while('0'<=ch&&ch<='9') {s=s+p*(ch^48);p/=10;ch=gc();}
		}
		s=f?-s:s;
	}
	template<class T,class ...A>
	inline void read(T &s,A &...a){
		read(s);read(a...);
	}
};
using IO::read;
const int inf=1e9;
#define int unsigned int
int n,mods,a;
inline int inc(int x,int y){
	return (x+=y)>=mods?x-mods:x;
}
inline int dec(int x,int y){
	return (x-=y)<0?x+mods:x;
}
inline int mul(int x,int y){
	return 1ll*x*y%mods;
}
inline int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}
template<class T,int MAXN,int MAXM>
struct StarList{
	StarList(){
		tot=-1;
		memset(head,-1,sizeof(head) );
	};
	int nxt[MAXM],head[MAXN],tot;
	T to[MAXM];
	inline void link(int u,T v){
		nxt[++tot]=head[u];
		head[u]=tot;
		to[tot]=v;
	}
};
int B;
struct HashMap{
	#define S (1145141)
	struct node{
		int x,id;
	};
	StarList<node,S+3,S+3>h;
	inline void ins(int x,int id){
		h.link(x%S,{x,id});
	}
	inline int find(int x){
		int mi=inf;
		for(int i=h.head[x%S];~i;i=h.nxt[i]){
			if(h.to[i].x==x){
				mi=std::min(mi,h.to[i].id);
			}
		}
		return mi;
	}
}ex;
signed main(){
	file(a);
	read(mods,a,n);
	B=sqrt(mods-1);
	int sum=n,inva=qpow(a,mods-2);
	for(int i=0;i<B;++i,sum=mul(sum,inva) ){
		ex.ins(sum,i);
	}
	int now=1,aB=qpow(a,B);
	for(int i=0;i<=mods-1;i+=B,now=mul(now,aB) ){
		int d;
		if((d=ex.find(now) )!=inf){
			printf("%d\n",i+d);
			return 0;
		}
	}
	printf("no solution\n");
	return 0;
}

这个做法需要的就是模数与基底互质,不互质的可以除最大公约数扩展。

参考资料

数论常见定理 - EricQian06

OI-wiki

posted @   cbdsopa  阅读(226)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示