AtCoder Beginner Contest 315 Ex. Typical Convolution Problem(分治NTT/全在线卷积)

news2025/1/10 12:00:05

题目

给定长为n(n<=2e5)的序列a,第i个数ai(0<=ai<998244353)

求序列f,满足式子如下:

eq?f_%7Bk%7D%20%3D%20%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%201%2C%20k%3D0%20%5C%5C%20a_%7Bk%7D*%5Csum_%7Bi&plus;j%3Cn%7Df_%7Bi%7D*f_%7Bj%7D%281%5Cleq%20k%20%5Cleq%20n%29%20%5Cend%7Bmatrix%7D%5Cright.

思路来源

jiangly代码/力扣群友tdzl2003/propane/自己的乱搞

29d5ac4d4d5f475182f8229299d96bdb.png

题解

分治NTT,考虑[l,mid]对[mid+1,r]的贡献

但是,手玩一下就会发现有个问题

 

举个例子,

1. [l,mid]=[0,1],[mid+1,r]=[2,3],那么右半边f2会加上f0*(f0+f1)+f1*f0,贡献完整

2. [l,mid]=[5,6],[mid+1,r]=[7,8],那么右半边f7会加上f5*(f0+f1)+f6*f0

相当于只有一半贡献,比如有f5*f0,没有f0*f5,

因为考虑f0所在区间对右的贡献时,f5还没算出来

对于第二种情况,贡献就需要乘以2

 

这两种情况会混在一起导致很难算么,答案是不会的

考虑第一次出现贡献完整,不需要*2的项时,

左边两个下标最小,右边下标最大,也就是l+l=r-1,满足2*l<r

由于分治NTT是分治的完整的2的幂次的区间,左右半段等长,

观察不难发现(jiangly代码告诉我们)只有l=0时,才会出现2*l<r

所以,分类讨论两种情况即可

Bonus

官方题解/群友给出了全在线卷积/半在线卷积的解法,更好理解,

一边卷积求第i项,一边维护卷积的前缀和

大概看了看是构造出了一个矩阵,

数字表示该数加入的时候算哪些矩阵,

每个矩阵对应一个边长规模的卷积

15574bc3424d4055bede3f71b277c344.png

从而保证任何时刻均摊都是n(logn)^2,可以考虑以后整理个板子(咕)……

代码1(参考)

时间大概是代码2的一半

l=r处求f[l]的值,卷积的前缀和也是在此处算的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std;
#define ll long long
#define ull unsigned ll
const int N = 1<<20, P = 998244353;
const int Primitive_root = 3;
struct Z{
    int x;
    Z(const int _x=0):x(_x){}
    Z operator +(const Z &r)const{ return x+r.x<P?x+r.x:x+r.x-P;}
    Z operator -(const Z &r)const{ return x<r.x?x-r.x+P:x-r.x;}
    Z operator -()const{ return x?P-x:0;}
    Z operator *(const Z &r)const{ return static_cast<ull>(x)*r.x%P;}
    Z operator +=(const Z &r){ return x=x+r.x<P?x+r.x:x+r.x-P, *this;}
    Z operator -=(const Z &r){ return x=x<r.x?x-r.x+P:x-r.x, *this;}
    Z operator *=(const Z &r){ return x=static_cast<ull>(x)*r.x%P, *this;}
    friend Z Pow(Z, int);
    pair<Z,Z> Mul(pair<Z,Z> x, pair<Z,Z> y, Z f)const{
        return make_pair(
            x.first*y.first+x.second*y.second*f,
            x.second*y.first+x.first*y.second
        );
    }
};
Z Pow(Z x, int y=P-2){
    Z ans=1;
    for(; y; y>>=1, x=x*x) if(y&1) ans=ans*x;
    return ans;
}
namespace Poly{
    Z w[N];
    Z Inv[N];
    vector<Z> ans;
    vector<vector<Z> > p;
    ull F[N];
    int Get_root(){
		static int pr[N],cnt;
		int n=P-1,sz=(int)(sqrt(n)),root=-1;
		for(int i=2;i<=sz;++i){if(n%i==0)pr[cnt++]=i;while(n%i==0)n/=i;}
		if(n>1)pr[cnt++]=n;
		for(int i=1;i<P;++i){
			if(Pow((Z)i,P-1).x==1){
				bool fl=true;
				for(int j=0;j<cnt;++j){
					if(Pow(i,(P-1)/pr[j]).x==1){
						fl=false;break;
					}
				}
				if(fl){root=i;break;}
			}
		}
		return root;
	}
    void Init(){
    	//printf("root:%d\n",Primitive_root=Get_root()); 先求出来原根然后当const用 
        for(int i=1; i<N; i<<=1){
            w[i]=1;
            Z t=Pow((Z)Primitive_root, (P-1)/i/2);
            for(int j=1; j<i; ++j) w[i+j]=w[i+j-1]*t;
        }
        Inv[1]=1;
        for(int i=2; i<N; ++i) Inv[i]=Inv[P%i]*(P-P/i);
    }
    int Get(int x){ int n=1; while(n<=x) n<<=1; return n;}
    int Mod(int x){ return x<P?x:x-P;}
    void DFT(vector<Z> &f, int n){
        if((int)f.size()!=n) f.resize(n);
        for(int i=0, j=0; i<n; ++i){
            F[i]=f[j].x;
            for(int k=n>>1; (j^=k)<k; k>>=1);
        }
        if(n<=4){
            for(int i=1; i<n; i<<=1) for(int j=0; j<n; j+=i<<1){
                Z *W=w+i;
                ull *F0=F+j, *F1=F+j+i;
                for(int k=j; k<j+i; ++k, ++W, ++F0, ++F1){
                    ull t=(*F1)*(W->x)%P;
                    (*F1)=*F0+P-t, (*F0)+=t;
                }
            }
        }
        else{
            for(int j=0; j<n; j+=2){
                int t=F[j+1];
                F[j+1]=Mod(F[j]+P-t), F[j]=Mod(F[j]+t);
            }
            for(int j=0; j<n; j+=4){
                int t0=F[j+2], t1=F[j+3]*w[3].x%P;
                F[j+2]=F[j]+P-t0, F[j]+=t0;
                F[j+3]=F[j+1]+P-t1, F[j+1]+=t1;
            }
            for(int i=4; i<n; i<<=1) for(int j=0; j<n; j+=i<<1){
                Z *W=w+i;
                ull *F0=F+j, *F1=F+j+i;
                for(int k=j; k<j+i; k+=4, W+=4, F0+=4, F1+=4){
                    int t0=(W->x)**F1%P;
                    int t1=(W+1)->x**(F1+1)%P;
                    int t2=(W+2)->x**(F1+2)%P;
                    int t3=(W+3)->x**(F1+3)%P;
                    *F1=*F0+P-t0, *F0+=t0;
                    *(F1+1)=*(F0+1)+P-t1, *(F0+1)+=t1;
                    *(F1+2)=*(F0+2)+P-t2, *(F0+2)+=t2;
                    *(F1+3)=*(F0+3)+P-t3, *(F0+3)+=t3;
                }
            }
        }
        for(int i=0; i<n; ++i) f[i]=F[i]%P;
    }
    void IDFT(vector<Z> &f, int n){
        f.resize(n), reverse(f.begin()+1, f.end()), DFT(f, n);
        Z I=1;
        for(int i=1; i<n; i<<=1) I*=(P+1)/2;
        for(int i=0; i<n; ++i) f[i]*=I;
    }
    vector<Z> operator +(const vector<Z> &f, const vector<Z> &g){
        vector<Z> ans=f;
        ans.resize(max(f.size(), g.size()));
        for(int i=0; i<(int)g.size(); ++i) ans[i]+=g[i];
        return ans;
    }
    vector<Z> operator *(const vector<Z> &f, const vector<Z> &g){
        static vector<Z> F, G;
        F=f, G=g;
        int p=Get(f.size()+g.size()-2);
        DFT(F, p), DFT(G, p);
        for(int i=0; i<p; ++i) F[i]*=G[i];
        IDFT(F, p);
        return F.resize(f.size()+g.size()-1), F;
    }
}
using namespace Poly;
int n;
Z fac[N],ifac[N];
void init(int n){
	fac[0]=1;
    for(int i=1;i<=n;++i){
		fac[i]=fac[i-1]*i;
    } 
	ifac[n]=Pow(fac[n]);
    for(int i=n;i;--i){
    	ifac[i-1]=ifac[i]*i;
    }
}
vector<Z>f,a,b,g,h;
void work(int l, int r){//左闭右开 
    if(l+1==r){
        if(l){
            f[l]=h[l-1]*g[l];
            h[l]+=h[l-1]+Z(2)*f[l];
        }
        else{
            f[l]=1;
            h[l]=1;
        }
        //printf("l:%d r:%d h:%d f:%d\n",l,r,h[l].x,f[l].x);
        return;
    }
    int mid=(l+r)>>1,sz=(r-l)>>1;
	work(l,mid); 
    if(l==0){
    	a.resize(r-l);b.resize(sz);
    	memset(&a[sz],0,sizeof(Z)*sz); //把a的右区间强制清0 (2,0)
        memcpy(&a[0],&f[l],sizeof(Z)*sz); //把a的左区间强制赋成f已经算的值 (2,0) 移到a的对应部分 
        memcpy(&b[0],&f[0],sizeof(Z)*sz); //把整个区间长度的g移动到b的位置 
        a=a*b;
        for(int i=sz;i<r-l;i++){//后半段加上左对右的贡献
            //printf("l:%d r:%d i:%d add:%d\n",l,r,i,a[i].x);
            h[l+i]+=a[i];
        }
    }
    else{
        a.resize(r-l);b.resize(r-l);
        memset(&a[sz],0,sizeof(Z)*sz); //把a的右区间强制清0 (2,0)
        memcpy(&a[0],&f[l],sizeof(Z)*sz); //把a的左区间强制赋成f已经算的值 (2,0) 移到a的对应部分 
        memcpy(&b[0],&f[0],sizeof(Z)*(r-l)); //把整个区间长度的g移动到b的位置
        a=a*b;
        for(int i=sz;i<r-l;i++){//后半段加上左对右的贡献
            //printf("l:%d r:%d i:%d add:%d\n",l,r,i,2*a[i].x);
            h[l+i]+=Z(2)*a[i];
        }
    }
	work(mid,r);
}
int main(){
    Init();
    init(N-1);
    scanf("%d",&n);
    int lg=1;
	while((1<<lg)<=n)lg++;
    //printf("lg:%d\n",lg);
	f.resize(1<<lg);f[0].x=1;
	g.resize(1<<lg);g[0].x=0;
    h.resize(1<<lg);h[0].x=0;
	for(int i=1;i<=n;++i){
		scanf("%d",&g[i].x);
	}
	work(0,1<<lg);
	for(int i=1;i<=n;++i){
		printf("%d%c",f[i].x," \n"[i==n]);
	} 	
    return 0;
}

代码2(乱搞)

左对右的贡献的前缀和是每次分治现求的,

反正时间瓶颈是做NTT的过程

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std;
#define ll long long
#define ull unsigned ll
const int N = 1<<20, P = 998244353;
const int Primitive_root = 3;
struct Z{
    int x;
    Z(const int _x=0):x(_x){}
    Z operator +(const Z &r)const{ return x+r.x<P?x+r.x:x+r.x-P;}
    Z operator -(const Z &r)const{ return x<r.x?x-r.x+P:x-r.x;}
    Z operator -()const{ return x?P-x:0;}
    Z operator *(const Z &r)const{ return static_cast<ull>(x)*r.x%P;}
    Z operator +=(const Z &r){ return x=x+r.x<P?x+r.x:x+r.x-P, *this;}
    Z operator -=(const Z &r){ return x=x<r.x?x-r.x+P:x-r.x, *this;}
    Z operator *=(const Z &r){ return x=static_cast<ull>(x)*r.x%P, *this;}
    friend Z Pow(Z, int);
    pair<Z,Z> Mul(pair<Z,Z> x, pair<Z,Z> y, Z f)const{
        return make_pair(
            x.first*y.first+x.second*y.second*f,
            x.second*y.first+x.first*y.second
        );
    }
};
Z Pow(Z x, int y=P-2){
    Z ans=1;
    for(; y; y>>=1, x=x*x) if(y&1) ans=ans*x;
    return ans;
}
namespace Poly{
    Z w[N];
    Z Inv[N];
    vector<Z> ans;
    vector<vector<Z> > p;
    ull F[N];
    int Get_root(){
        static int pr[N],cnt;
        int n=P-1,sz=(int)(sqrt(n)),root=-1;
        for(int i=2;i<=sz;++i){if(n%i==0)pr[cnt++]=i;while(n%i==0)n/=i;}
        if(n>1)pr[cnt++]=n;
        for(int i=1;i<P;++i){
            if(Pow((Z)i,P-1).x==1){
                bool fl=true;
                for(int j=0;j<cnt;++j){
                    if(Pow(i,(P-1)/pr[j]).x==1){
                        fl=false;break;
                    }
                }
                if(fl){root=i;break;}
            }
        }
        return root;
    }
    void Init(){
        //printf("root:%d\n",Primitive_root=Get_root()); 先求出来原根然后当const用 
        for(int i=1; i<N; i<<=1){
            w[i]=1;
            Z t=Pow((Z)Primitive_root, (P-1)/i/2);
            for(int j=1; j<i; ++j) w[i+j]=w[i+j-1]*t;
        }
        Inv[1]=1;
        for(int i=2; i<N; ++i) Inv[i]=Inv[P%i]*(P-P/i);
    }
    int Get(int x){ int n=1; while(n<=x) n<<=1; return n;}
    int Mod(int x){ return x<P?x:x-P;}
    void DFT(vector<Z> &f, int n){
        if((int)f.size()!=n) f.resize(n);
        for(int i=0, j=0; i<n; ++i){
            F[i]=f[j].x;
            for(int k=n>>1; (j^=k)<k; k>>=1);
        }
        if(n<=4){
            for(int i=1; i<n; i<<=1) for(int j=0; j<n; j+=i<<1){
                Z *W=w+i;
                ull *F0=F+j, *F1=F+j+i;
                for(int k=j; k<j+i; ++k, ++W, ++F0, ++F1){
                    ull t=(*F1)*(W->x)%P;
                    (*F1)=*F0+P-t, (*F0)+=t;
                }
            }
        }
        else{
            for(int j=0; j<n; j+=2){
                int t=F[j+1];
                F[j+1]=Mod(F[j]+P-t), F[j]=Mod(F[j]+t);
            }
            for(int j=0; j<n; j+=4){
                int t0=F[j+2], t1=F[j+3]*w[3].x%P;
                F[j+2]=F[j]+P-t0, F[j]+=t0;
                F[j+3]=F[j+1]+P-t1, F[j+1]+=t1;
            }
            for(int i=4; i<n; i<<=1) for(int j=0; j<n; j+=i<<1){
                Z *W=w+i;
                ull *F0=F+j, *F1=F+j+i;
                for(int k=j; k<j+i; k+=4, W+=4, F0+=4, F1+=4){
                    int t0=(W->x)**F1%P;
                    int t1=(W+1)->x**(F1+1)%P;
                    int t2=(W+2)->x**(F1+2)%P;
                    int t3=(W+3)->x**(F1+3)%P;
                    *F1=*F0+P-t0, *F0+=t0;
                    *(F1+1)=*(F0+1)+P-t1, *(F0+1)+=t1;
                    *(F1+2)=*(F0+2)+P-t2, *(F0+2)+=t2;
                    *(F1+3)=*(F0+3)+P-t3, *(F0+3)+=t3;
                }
            }
        }
        for(int i=0; i<n; ++i) f[i]=F[i]%P;
    }
    void IDFT(vector<Z> &f, int n){
        f.resize(n), reverse(f.begin()+1, f.end()), DFT(f, n);
        Z I=1;
        for(int i=1; i<n; i<<=1) I*=(P+1)/2;
        for(int i=0; i<n; ++i) f[i]*=I;
    }
    vector<Z> operator +(const vector<Z> &f, const vector<Z> &g){
        vector<Z> ans=f;
        ans.resize(max(f.size(), g.size()));
        for(int i=0; i<(int)g.size(); ++i) ans[i]+=g[i];
        return ans;
    }
    vector<Z> operator *(const vector<Z> &f, const vector<Z> &g){
        static vector<Z> F, G;
        F=f, G=g;
        int p=Get(f.size()+g.size()-2);
        DFT(F, p), DFT(G, p);
        for(int i=0; i<p; ++i) F[i]*=G[i];
        IDFT(F, p);
        return F.resize(f.size()+g.size()-1), F;
    }
}
using namespace Poly;
int n;
Z fac[N],ifac[N];
void init(int n){
    fac[0]=1;
    for(int i=1;i<=n;++i){
        fac[i]=fac[i-1]*i;
    } 
    ifac[n]=Pow(fac[n]);
    for(int i=n;i;--i){
        ifac[i-1]=ifac[i]*i;
    }
}
vector<Z>f,a,b,g;
void work(int l, int r){//左闭右开 
    if(l+1==r)return;
    int mid=(l+r)>>1,sz=(r-l)>>1;
    work(l,mid); 
    int up=min(r-l,l);
    //printf("up:%d\n",up);
    if(up){
        a.resize(r-l);b.resize(up);
        memset(&a[sz],0,sizeof(Z)*sz); //把a的右区间强制清0 (2,0)
        memcpy(&a[0],&f[l],sizeof(Z)*sz); //把a的左区间强制赋成f已经算的值 (2,0) 移到a的对应部分 
        memcpy(&b[0],&f[0],sizeof(Z)*up); //把整个区间长度的g移动到b的位置 
        a=a*b; 
        for(int i=1;i<r-l;++i){
            a[i]+=a[i-1];
        }
        for(int i=sz;i<r-l;i++){//后半段加上左对右的贡献
            int w=i-1<0?0:2ll*a[i-1].x%P;
            f[l+i]+=Z(w)*g[l+i];
        }
    }
    a.resize(r-l);b.resize(sz);
    memset(&a[sz],0,sizeof(Z)*sz); //把a的右区间强制清0 (2,0)
    memcpy(&a[0],&f[l],sizeof(Z)*sz); //把a的左区间强制赋成f已经算的值 (2,0) 移到a的对应部分 
    memcpy(&b[0],&f[l],sizeof(Z)*sz); //把整个区间长度的g移动到b的位置
    a=a*b; 
    for(int i=1;i<r-l;++i){
        a[i]+=a[i-1];
    }
    for(int i=sz;i<r-l;i++){//后半段加上左对右的贡献
        int w=i-1-l<0?0:a[i-1-l].x;
        f[l+i]+=Z(w)*g[l+i];
    }
    work(mid,r);
}
int main(){
    Init();
    init(N-1);
    scanf("%d",&n);
    int lg=1;
    while((1<<lg)<=n)lg++;
    //printf("lg:%d\n",lg);
    f.resize(1<<lg);f[0].x=1;
    g.resize(1<<lg);g[0].x=0;
    for(int i=1;i<=n;++i){
        scanf("%d",&g[i].x);
    }
    work(0,1<<lg);
    for(int i=1;i<=n;++i){
        printf("%d%c",f[i].x," \n"[i==n]);
    }   
    return 0;
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/970080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RT-Thread I/O设备模型(二)

访问I/O设备 应用程序通过I/O设备管理接口来访问硬件设备&#xff0c;当设备驱动程序实现后&#xff0c;应用程序就可以访问该硬件。I/O设备管理接口与I/O设备的操作方法映射关系如下&#xff1a; 查找设备 应用程序根据设备名称获取设备句柄&#xff0c;进而操作设备。 rt_…

MybatisPlus基本配置查询操作

无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响&#xff0c;如丝般顺滑损耗小&#xff1a;启动即会自动注入基本 CURD&#xff0c;性能基本无损耗&#xff0c;直接面向对象操作强大的 CRUD 操作&#xff1a;内置通用 Mapper、通用 Service&#…

手把手教你用Vite构建第一个Vue3项目

写在前面 在之前的文章中写过“如何创建第一个vue项目”&#xff0c;但那篇文章写的是创建vue2的 项目。 传送门如何创建第一个vue项目 打开Vue.js官网:https://cn.vuejs.org/&#xff0c;我们会发现Vue 2 将于 2023 年 12 月 31 日停止维护 虽然Vue2的项目还不少&#xff0…

day5 qt

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);timer_idthis->startTimer(100);//啓動一個定時器 每100ms發送一次信號ui->Edit1->setPlaceholderTex…

Leetcode:349. 两个数组的交集【题解超详细】

题目 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 难度&#xff1a;简单 题目链接&#xff1a;349.两个数组的交集 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,…

CentOS7上源码安装Redis6

CentOS7上源码安装Redis6 安装依赖开始安装下载安装包解压安装包编译源代码修改配置文件 启动并连接启动redis服务器本地连接远程连接 下篇预告 安装依赖 首先我们是源码包安装我们需要安装C语言编译器&#xff0c;顺便下载wget&#xff1a; yum install -y gcc wget开始安装…

Ab3d.PowerToys 11.0.8614 Crack

版本 11.0.8614 修补程序 使用 MouseCameraController 移动相机时防止旋转 FreeCamera。 版本 11.0.8585 重大更改&#xff1a;由于专利问题删除了 ViewCubeCameraController - 请联系支持人员以获取更多信息以及如果您想继续使用此控件。添加了 CameraNavigationCircles 控件…

第12节——生命周期

一、概念 生命周期指 React 组件从装载至卸载的全过程&#xff0c;这个过程内置多个函数供开发者在组件的不同阶段执行需要的逻辑。 状态组件主要通过 3 个生命周期阶段来管理&#xff0c;分别是 挂载阶段&#xff08;MOUNTING&#xff09;&#xff0c;更新阶段&#xff08;U…

AJAX学习笔记3练习

AJAX学习笔记2发送Post请求_biubiubiu0706的博客-CSDN博客 1.验证用户名是否可用 需求,用户输入用户名,失去焦点-->onblur失去焦点事件,发送AJAX POST请求,验证用户名是否可用 新建表 前端页面 WEB-INF下新建lib包引入依赖,要用JDBC 后端代码 package com.web;import jav…

ModaHub魔搭社区:自动化机器学习框架AutoML

AutoML 自动化机器学习AutoML 是机器学习中一个相对较新的领域,它主要将机器学习中所有耗时过程自动化,如数据预处理、最佳算法选择、超参数调整等,这样可节约大量时间在建立机器学习模型过程中。 自动机器学习 AutoML: 对于 ,令 表示特征向量, 表示对应的目标值。给定…

基于SpringCloudAlibaba实现的NacosConfig

概述 Nacos除了实现了服务的注册发现之外&#xff0c;还将配置中心功能整合在了一起。通过Nacos的配置管理功能&#xff0c;我们可以将整个架构体系内的所有配置都集中在Nacos中存储。这样做的好处主要有以下几点&#xff1a; 分离的多环境配置&#xff0c;可以更灵活的管理权…

基于Java+SpringBoot+Vue前后端分离大学生智能消费记账系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

基于Java+SpringBoot+Vue前后端分离农商对接系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

机器人中的数值优化(十三)——QP二次规划

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

MLOps:掌握机器学习部署:Docker、Kubernetes、Helm 现代 Web 框架

介绍&#xff1a; 在机器学习的动态世界中&#xff0c;从开发模型到将其投入生产的过程通常被认为是复杂且多方面的。 然而&#xff0c;随着 Docker、Kubernetes 等工具以及 FastAPI、Streamlit 和 Gradio 等用户友好的 Web 框架的出现&#xff0c;这一过程变得比以往更加简化…

CS420 课程笔记 P3 - 计数系统基础和 Hex, Decimal, Binary 进制

文章目录 IntroductionInspirationWhy base systemsBinary & HexCounting in binaryAdditional resources Introduction 笔记作者 tips&#xff1a;这一节是关于进制的讲解&#xff0c;推荐观看原视频或学会二进制的读者跳过这一篇&#xff01; 本节课将介绍基本的计算机系…

台球击球角度公式. 包含数学推导

第一步. 物理来分析. 第二步. 数学计算.

【jsvue】联合gtp仿写一个简单的vue框架,以此深度学习JavaScript

用 gtp 学习 Vue 生命周期的原理 lifecycle.js function Vue(options) {// 将选项保存到实例的 $options 属性中this.$options options;// 若存在 beforeCreate 钩子函数&#xff0c;则调用之if (typeof options.beforeCreate function) {options.beforeCreate.call(this);…

Qt 5.15编译及集成Crypto++ 8.7.0笔记

一、背景 为使用AES加密库&#xff08;AES/CBC加解密&#xff09;&#xff0c;选用Crypto 库&#xff08;官网&#xff09;。   最新Crypto C库依次为&#xff1a;8.8.0版本&#xff08;2023-6-25&#xff09;、8.7.0&#xff08;2022-8-7&#xff09;和8.6.0&#xff08;202…

MySQL数据库——多表查询(4)-实例练习、多表查询总结

目录 练习1 练习2 总结 1.多表关系 2.多表查询 进行案例练习之前&#xff0c;需要先增加一个表格 create table salgrade(grade int,losal int, -- 对应等级的最低薪资hisal int -- 对应等级的最高薪资 ) comment 薪资等级表;insert into salgrade values (1,0,3000)…