板子
板子
高精
namespace BIG_num{ using cpx=complex<double>; const double PI=acos(-1); vector<cpx>roots= {{0,0},{1,0}}; void ensure_capacity(int min_capacity) { for(int len=roots.size();len<min_capacity;len*=2) for(int i=len>>1; i<len; i++) { roots.emplace_back(roots[i]); double angle=2*PI*(2*i+1-len)/(len*2); roots.emplace_back(cos(angle),sin(angle)); } } void fft(vector<cpx>&z,bool inverse) { int n=z.size(); ensure_capacity(n); for(int i=1,j=0;i<n;i++){int BIGt=n>>1; for(; j>=BIGt; BIGt>>=1) j-=BIGt; j+=BIGt; if(i<j) swap(z[i],z[j]);} for(int len=1;len<n;len<<=1) for(int i=0;i<n;i+=len*2) for(int j=0;j<len;j++){ cpx root=inverse?conj(roots[j+len]):roots[j+len],u=z[i+j],v=z[i+j+len]*root; z[i+j]=u+v;z[i+j+len]=u-v; } if(inverse)for(int i=0; i<n; i++)z[i]/=n; } vector<int>multiply_BIG(const vector<int>&a,const vector<int>&b,int base) { int need=a.size()+b.size(); int n=1; while(n<need) n<<=1; vector<cpx> p(n); for(int i=0;i<n;i++) p[i]=cpx(i<(int)a.size()?a[i]:0,i<(int)b.size()?b[i]:0); fft(p,false); vector<cpx>ab(n); cpx r(0,-0.25); for(int i=0;i<n;i++){int j=(n-i)&(n-1); ab[i]=(p[i]*p[i]-conj(p[j]*p[j]))*r;} fft(ab,true); vector<int>result(need); long long carry=0; for(int i=0;i<need;i++){long long d=(long long)(ab[i].real()+0.5)+carry; carry=d/base;result[i]=d%base;} return result; } vector<int>multiply_mod(const vector<int>&a,const vector<int>&b,int m) { int need=a.size()+b.size()-1; int n=1; while(n<need)n<<=1; vector<cpx>A(n); for(size_t i=0;i<a.size();i++){int x=(a[i]%m+m)%m; A[i]=cpx(x&((1<<15)-1),x>>15);} fft(A,false); vector<cpx>B(n); for(size_t i=0;i<b.size();i++){int x=(b[i]%m+m)%m; B[i]=cpx(x&((1<<15)-1),x>>15);} fft(B,false); vector<cpx>fa(n); vector<cpx>fb(n); for(int i=0,j=0;i<n;i++,j=n-i) { cpx a1=(A[i]+conj(A[j]))*cpx(0.5,0),a2=(A[i]-conj(A[j]))*cpx(0,-0.5); cpx b1=(B[i]+conj(B[j]))*cpx(0.5,0),b2=(B[i]-conj(B[j]))*cpx(0,-0.5); fa[i]=a1*b1+a2*b2*cpx(0,1); fb[i]=a1*b2+a2*b1; } fft(fa,true); fft(fb,true); vector<int>res(need); for(int i=0;i<need;i++){ long long aa=(long long)(fa[i].real()+0.5),bb=(long long)(fb[i].real()+0.5),cc=(long long)(fa[i].imag()+0.5); res[i]=(aa%m+(bb%m<<15)+(cc%m<<30))%m; } return res; } constexpr int digits(int base)noexcept{return base<=1?0:1+digits(base/10);} constexpr int base=1000000000,base_digits=digits(base),fft_base=10000,fft_base_digits=digits(fft_base); struct Big { vector<int>z; int sign; Big(long long v=0){*this=v;} Big &operator=(long long v){ sign=v<0?-1:1,v*=sign,z.clear(); for(;v>0;v=v/base) z.push_back((int)(v%base)); return *this; } Big (const string &s){read(s);} Big &operator+=(const Big &other){ if(sign==other.sign) for(int i=0,carry=0;i<(int)other.z.size()||carry;++i){ if(i==(int)z.size()) z.push_back(0); z[i]+=carry+(i<(int)other.z.size()?other.z[i]:0),carry=z[i]>=base;if(carry)z[i]-=base; }else if(other!=0) {*this-=-other;}return*this; } friend Big operator+(Big a,const Big &b){a+=b; return a;} Big &operator-=(const Big &other){ if(sign==other.sign){ if((sign==1&&*this>=other)||(sign==-1&&*this<=other)){ for(int i=0,carry=0;i<(int)other.z.size()||carry;++i){ z[i]-=carry+(i<(int)other.z.size()?other.z[i]:0),carry=z[i]<0; if(carry) z[i]+=base; } trim(); } else *this=other-*this,this->sign=-this->sign; } else {*this+=-other;}return*this; } friend Big operator-(Big a,const Big &b) {a-=b; return a;} Big &operator*=(int v){ if(v<0) sign=-sign,v=-v; for (int i=0,carry=0;i<(int)z.size()||carry;++i){ if(i==(int)z.size()) z.push_back(0); long long cur=(long long)z[i]*v+carry; carry=(int)(cur/base);z[i]=(int)(cur%base); } trim(); return*this; } Big operator*(int v)const{return Big(*this)*=v;} friend pair<Big,Big>divmod(const Big&a1,const Big&b1) { int norm=base/(b1.z.back()+1); Big a=a1.abs()*norm,b=b1.abs()*norm,q,r; q.z.resize(a.z.size()); for(int i=(int)a.z.size()-1;i>=0;i--) { r*=base,r+=a.z[i]; int s1=b.z.size()<r.z.size()?r.z[b.z.size()]:0,s2=b.z.size()-1<r.z.size()?r.z[b.z.size()-1]:0; int d=(int)(((long long)s1*base+s2)/b.z.back()); r-=b*d;while(r<0)r+=b,--d;q.z[i]=d; } q.sign=a1.sign*b1.sign,r.sign=a1.sign; q.trim(),r.trim(); return {q,r/norm}; } friend Big sqrt(const Big&a1){ Big a=a1; while(a.z.empty()||a.z.size()%2==1) a.z.push_back(0); int n=a.z.size(),firstDigit=(int)::sqrt((double)a.z[n-1]*base+a.z[n-2]),norm=base/(firstDigit+1); a*=norm,a*=norm; while(a.z.empty()||a.z.size()%2==1) a.z.push_back(0); Big r=(long long)a.z[n-1]*base+a.z[n-2],res; firstDigit=(int)::sqrt((double)a.z[n-1]*base+a.z[n-2]); int q=firstDigit; for(int j=n/2-1;j>=0;j--){ for(;;--q){ Big r1=(r-(res*2*base+q)*q)*base*base+(j>0?(long long)a.z[2*j-1]*base+a.z[2*j-2]:0); if(r1>=0){r=r1; break;} } res*=base;res+=q; if(j>0){ int d1=res.z.size()+2<r.z.size()?r.z[res.z.size()+2]:0; int d2=res.z.size()+1<r.z.size()?r.z[res.z.size()+1]:0; int d3=res.z.size()<r.z.size()?r.z[res.z.size()]:0; q=(int)(((long long)d1*base*base+(long long)d2*base+d3)/(firstDigit*2)); } } res.trim(); return res/norm; } Big operator/(const Big&v)const{return divmod(*this,v).first;} Big operator%(const Big&v)const{return divmod(*this,v).second;} Big &operator/=(int v){ if(v<0) sign=-sign,v=-v; for(int i=(int)z.size()-1,rem=0;i>=0;--i){ long long cur=z[i]+rem*(long long)base; z[i]=(int)(cur/v),rem=(int)(cur%v); } trim();return*this; } Big operator/(int v)const{return Big(*this)/=v;} int operator%(int v) const { if(v<0) v=-v; int m=0; for(int i=(int)z.size()-1;i>=0;--i) m=(int)((z[i]+m*(long long)base)%v); return m*sign; } Big&operator*=(const Big &v){*this=*this*v; return*this;} Big&operator/=(const Big &v){*this=*this/v; return*this;} Big&operator%=(const Big &v){*this=*this%v; return*this;} friend bool operator<(const Big &u,const Big &v){ if(u.sign!=v.sign) return u.sign<v.sign; if(u.z.size()!=v.z.size()) return u.z.size()*u.sign<v.z.size()*v.sign; for(int i=(int)u.z.size()-1;i>=0;i--) if(u.z[i]!=v.z[i]) return u.z[i]*u.sign<v.z[i]*v.sign; return false; } friend bool operator>(const Big &u,const Big &v){return v<u;} friend bool operator<=(const Big &u,const Big &v){return !(v<u);} friend bool operator>=(const Big &u,const Big &v){return !(u<v);} friend bool operator==(const Big &u,const Big &v){return u.sign==v.sign&&u.z==v.z;} friend bool operator!=(const Big &u,const Big &v){return !(u==v);} void trim(){while(!z.empty()&&z.back()==0) z.pop_back(); if(z.empty()) sign=1;} bool isZero()const{return z.empty();} friend Big operator-(Big v){if(!v.z.empty()) v.sign=-v.sign; return v;} Big abs()const{return sign==1?*this:-*this;} long long to_num()const{ long long res=0; for(int i=(int)z.size()-1;i>=0;i--) res=res*base+z[i]; return res*sign; } friend Big __gcd(const Big &a,const Big &b){return b.isZero()?a:__gcd(b,a%b);} friend Big abs(const Big &a){return a.abs();} void read(const string &s){ sign=1,z.clear(); int pos=0; while(pos<(int)s.size()&&(s[pos]=='-'||s[pos]=='+')){if(s[pos]=='-') sign=-sign; ++pos;} for(int i=(int)s.size()-1;i>=pos;i-=base_digits){ int x=0; for(int j=max(pos,i-base_digits+1);j<=i;j++) x=x*10+s[j]-'0'; z.push_back(x); } trim(); } friend istream&operator>>(istream &stream,Big &v){string s; stream>>s; v.read(s); return stream;} friend ostream&operator<<(ostream &stream,const Big &v){ if(v.sign==-1) stream<<'-'; stream<<(v.z.empty()?0:v.z.back()); for(int i=(int)v.z.size()-2; i>=0; --i) stream<<setw(base_digits)<<setfill('0')<<v.z[i]; return stream; } static vector<int>convert_base(const vector<int>&a,int old_digits,int new_digits){ vector<long long> p(max(old_digits,new_digits)+1); p[0]=1; for(int i=1;i<(int)p.size();i++) p[i]=p[i-1]*10; vector<int> res; long long cur=0; int cur_digits=0; for(int v:a) { cur+=v*p[cur_digits],cur_digits+=old_digits; while(cur_digits>=new_digits) res.push_back(int(cur%p[new_digits])),cur/=p[new_digits],cur_digits -= new_digits; } res.push_back((int)cur); while(!res.empty()&&res.back()==0) res.pop_back(); return res; } Big operator*(const Big&v)const{ if(min(z.size(),v.z.size())<150) return mul_simple(v); Big res;res.sign=sign*v.sign; res.z=multiply_BIG(convert_base(z,base_digits,fft_base_digits), convert_base(v.z,base_digits,fft_base_digits),fft_base); res.z=convert_base(res.z,fft_base_digits,base_digits); res.trim(); return res; } Big mul_simple(const Big&v)const{Big res;res.sign=sign*v.sign;res.z.resize(z.size()+v.z.size()); for(int i=0;i<(int)z.size();++i) if(z[i]) for(int j=0,carry=0;j<(int)v.z.size()||carry;++j){ long long cur=res.z[i+j]+(long long)z[i]*(j<(int)v.z.size()?v.z[j]:0)+carry; carry=(int)(cur/base),res.z[i+j]=(int)(cur%base); } res.trim(); return res; } }; mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count()); Big BIG_rnd(int n){string s; for(int i=0;i<n;i++){s+=uniform_int_distribution<int>('0','9')(rng);} return Big(s);} } using BIG_num::Big;
可以像其他变量一样用 cin
和 cout
。
如 cin>>a>>b;
定义一个 BIG a;
可以连续定义:
如 BIG a=2,b,c=3;
加减乘除和一般变量一样,支持 +=
一类的,支持比较大小,不支持 BIG 转 int 等,但反过来支持。
分数
template<class Int> class Frac{ public: Int top,btm; Frac(){top=0;btm=1;} Frac(Int x){top=x;btm=1;} Frac(Int x,Int y){assert(y!=0); top=x,btm=y; this->normalize();} double to_num(){return (double)top/btm;} friend inline Frac abs(const Frac& x){return Frac(ibs(x.top),x.btm);} friend inline Frac Rec(const Frac& x){return Frac(x.btm,x.top);} friend inline Frac operator-(const Frac& x){return Frac(-x.top,x.btm);} Frac& operator++(){top+=btm; return *this;} Frac& operator--(){top-=btm; return *this;} Frac operator++(int){Frac x(top); top+=btm; return x;} Frac operator--(int){Frac x(top); top-=btm; return x;} Frac& operator+=(const Frac& x){ Int g=Gcd(btm,x.btm); top=btm/g*x.top+x.btm/g*top,btm*=x.btm/g; this->normalize(); return *this; } Frac& operator-=(const Frac& x){return *this+=(-x);} Frac& operator*=(const Frac& x){ Int g1=Gcd(ibs(top),x.btm),g2=Gcd(ibs(x.top),btm); (top/=g1)*=x.top/g2;(btm/=g2)*=x.btm/g1; return *this; } Frac& operator/=(const Frac& x){return *this*=Rec(x);} Frac friend operator+(Frac x,const Frac& y){return x+=y;} Frac friend operator-(Frac x,const Frac& y){return x-=y;} Frac friend operator*(Frac x,const Frac& y){return x*=y;} Frac friend operator/(Frac x,const Frac& y){return x/=y;} #define logical_operator(op) bool operator op(const Frac<Int>& y){return (*this-y).top op 0;} logical_operator(<) logical_operator(>) logical_operator(<=) logical_operator(>=) logical_operator(==) #undef logical_operator #define logical_operator(op) template<class U> bool operator op(U y){return (*this-Frac(y)).top op 0;} logical_operator(<) logical_operator(>) logical_operator(<=) logical_operator(>=) logical_operator(==) #undef logical_operator #define logical_operator(op) template<class U> friend bool operator op(U x,const Frac& y){return (Frac(x)-y).top op 0;} logical_operator(<) logical_operator(>) logical_operator(<=) logical_operator(>=) logical_operator(==) #undef logical_operator friend istream&operator>>(istream &stream,Frac &v){stream>>v.top>>v.btm; v.normalize(); return stream;} friend ostream&operator<<(ostream &stream,const Frac &v){stream<<v.top<<'/'<<v.btm; return stream;}//在此更改输出格式 private: inline Int Gcd(Int a,Int b){while(b) swap((a%=b),b); return a;} Int ibs(const Int& a){return a<0?-a:a;} inline void normalize(){Int g=Gcd(ibs(top),btm); top/=g,btm/=g;} };
定义时要加分子分母类型,类型支持上面的高精。
如果一次性赋值分子分母,用括号括起来。
如 Frac<int> a(1,3),b=(2,4)
。
取模数
template<class T> class Modular{ public: using Type = typename decay<decltype(T::val)>::type; constexpr static Type mod(){return T::val;} constexpr Modular():val(){}; template<class U> Modular(const U& x){val=normalize(x);} template<class U> static Type normalize(const U& x) { Type v=static_cast<Type>((-mod()<=x&&x<mod())?x:x%mod()); return (v<0)?v+mod():v; } const Type& operator()()const{return val;} template<class U> explicit operator U()const{return static_cast<U>(val);} Modular& operator+=(const Modular& other){if((val+=other.val)>=mod()) val-=mod(); return *this;} Modular& operator-=(const Modular& other){if((val-=other.val)<0) val+=mod(); return *this;} template<class U> Modular& operator+=(const U& other){return *this+=Modular(other);} template<class U> Modular& operator-=(const U& other){return *this-=Modular(other);} Modular& operator++(){if(!((++val)^mod())) val=0; return *this;} Modular& operator--(){if(!((--val)^(-1))) val=mod()-1; return *this;} Modular operator++(int){Modular result(*this); if(!((++val)^mod())) val=0; return result;} Modular operator--(int){Modular result(*this); if(!((--val)^(-1))) val=mod()-1; return result;} Modular operator-()const{return Modular(-val);} template<class U=T> typename enable_if<is_same<typename Modular<U>::Type,int>::value,Modular>::type& operator*=(const Modular& rhs){ val=normalize(static_cast<long long>(val)*static_cast<long long>(rhs.val)); return *this; } template<class U=T> typename enable_if<is_same<typename Modular<U>::Type,long long>::value,Modular>::type& operator*=(const Modular& rhs) { long long q=static_cast<long long>(static_cast<long double>(val)*rhs.val/mod()); val=normalize(val*rhs.val-q*mod()); return *this; } template<class U=T> typename enable_if<!is_integral<typename Modular<U>::Type>::value,Modular>::type& operator*=(const Modular& rhs) { val=normalize(val*rhs.val); return *this; } Modular& operator/=(const Modular& other){return *this*=Modular(Inv(other.val,mod()));} friend const Type& abs(const Modular& x){return x.val;} template<class V> friend bool operator==(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val==rhs.val;} template<class V,class U> friend bool operator==(const Modular<V>& lhs,U rhs){return lhs==Modular<V>(rhs);} template<class V,class U> friend bool operator==(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)==rhs;} template<class V> friend bool operator!=(const Modular<V>& lhs,const Modular<V>& rhs){return !(lhs==rhs);} template<class V,class U> friend bool operator!=(const Modular<V>& lhs,U rhs){return !(lhs==rhs);} template<class V,class U> friend bool operator!=(U lhs,const Modular<V>& rhs){return !(lhs==rhs);} template<class V> friend bool operator<(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val<rhs.val;} template<class V,class U> friend bool operator<(const Modular<V>& lhs,U rhs){return lhs<Modular<V>(rhs);} template<class V,class U> friend bool operator<(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)<rhs;} template<class V> friend bool operator<=(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val<=rhs.val;} template<class V,class U> friend bool operator<=(const Modular<V>& lhs,U rhs){return lhs<=Modular<V>(rhs);} template<class V,class U> friend bool operator<=(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)<=rhs;} template<class V> friend bool operator>(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val>rhs.val;} template<class V,class U> friend bool operator>(const Modular<V>& lhs,U rhs){return lhs>Modular<V>(rhs);} template<class V,class U> friend bool operator>(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)>rhs;} template<class V> friend bool operator>=(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val>=rhs.val;} template<class V,class U> friend bool operator>=(const Modular<V>& lhs,U rhs){return lhs>=Modular<V>(rhs);} template<class V,class U> friend bool operator>=(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)>=rhs;} template<class V> friend Modular<V> operator+(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)+=rhs;} template<class V,class U> friend Modular<V> operator+(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)+=rhs;} template<class V,class U> friend Modular<V> operator+(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)+=rhs;} template<class V> friend Modular<V> operator-(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)-=rhs;} template<class V,class U> friend Modular<V> operator-(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)-=rhs;} template<class V,class U> friend Modular<V> operator-(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)-=rhs;} template<class V> friend Modular<V> operator*(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)*=rhs;} template<class V,class U> friend Modular<V> operator*(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)*=rhs;} template<class V,class U> friend Modular<V> operator*(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)*=rhs;} template<class V> friend Modular<V> operator/(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)/=rhs;} template<class V,class U> friend Modular<V> operator/(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)/=rhs;} template<class V,class U> friend Modular<V> operator/(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)/=rhs;} template<class V> friend string to_string(const Modular<V>& number){return to_string(number());} template<class V> friend istream&operator>>(istream &stream,Modular<V>& v){ stream>>v.val; v.val=normalize(v.val); return stream; } template<class V> friend ostream&operator<<(ostream &stream,const Modular<V>& v){stream<<v(); return stream;} private: Type val; template<class V> V Inv(const V& x,const V& m) { assert(x!=0); V u=0,v=1,a=x,b=m,t; while(a!=0) t=b/a,swap(a,b-=t*a),swap(u-=t*v,v); assert(b==1); return u; } };
定义类似:
struct VarMod{static const int val=998244353;}; using Mint=Modular<VarMod>; // 固定模数 Mint a;
struct VarMod{static int val;}; int VarMod::val; int& MOD = VarMod::val; using Mint=Modular<VarMod>; // 不固定模数,通过修改 MOD 改变模数 Mint a;
计算几何:
const double Eps=1e-8; int Cmp(double a,double b){return fabs(a-b)<Eps?0:(a<b?-1:1);} struct Pnt{double x,y; Pnt(){} Pnt(double a,double b):x(a),y(b){}}; double Dis(const Pnt &a,const Pnt &b){return sqrtl((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} struct Vec{ double x,y; Vec(){} Vec(double a,double b):x(a),y(b){} Vec(const Pnt &a,const Pnt &b):x(b.x-a.x),y(b.y-a.y){} Vec &operator+=(const Vec &b){x+=b.x,y+=b.y; return *this;} Vec operator-()const{return Vec(-x,-y);} Vec &operator-=(const Vec &b){*this+=-b; return *this;} Vec operator+(const Vec &b)const{Vec ans=*this; return ans+=b;} Vec operator-(const Vec &b)const{Vec ans=*this; return ans-=b;} Vec &operator*=(double k){x*=k,y*=k; return *this;} friend Vec operator*(double k,Vec a){a*=k; return a;} Vec operator*(double k)const{return k*(*this);} double operator*(const Vec &b)const{return x*b.x+y*b.y;} double operator^(const Vec &b)const{return x*b.y-y*b.x;} }; struct Lin{ Pnt a,b; Lin(){} Lin(const Pnt &a1,const Pnt &a2):a(a1),b(a2){} Lin(double a1,double a2,double a3,double a4):a(a1,a2),b(a3,a4){} operator Vec()const{return Vec(a,b);} operator double()const{return Dis(a,b);} }; double Dis(const Pnt &p,const Lin &l){ if(Vec(l.a,p)*Vec(l.a,l.b)<0) return Dis(p,l.a); if(Vec(l.b,p)*Vec(l.b,l.a)<0) return Dis(p,l.b); return abs(Vec(l.a,l.b)^Vec(l.a,p))/double(l); }
本文来自博客园,作者:5k_sync_closer,转载请注明原文链接:https://www.cnblogs.com/xrlong/articles/18050639
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】