首页 > 其他分享 >「NOIP2022」比赛

「NOIP2022」比赛

时间:2024-11-09 19:58:18浏览次数:1  
标签:Tag const 比赛 int res tag ull NOIP2022

洛谷

题目简述

给定两个数列 \(a,b\),有 \(q\) 次询问,每次询问 \([L,R]\) 的所有子区间 \([l,r]\) 的 \(\max_{i=l}^r a_i \times \max_{i=l}^r b_i\) 之和。其中,\(n,q \le 2.5e5\)。

分析

这很像历史版本和,但是我们写过的只有一个数组 \(a\) 的。那么先从部分分开始。

对于 \(n,q \le 3000\) 这一档直接 \(O(n^2)\) 暴力。期望得分 \(20 pts\)。

代码

namespace sub1{
	#define N 3010
	ull val[N][N];
	void solve(){
		for(int i = 1;i<=n;++i){
			ull A = a[i], B = b[i];
			val[i][i] = 1ull * A * B;
			for(int j = i+1;j<=n;++j){
				A = max(A,a[j]), B = max(B,b[j]);
				val[i][j] = 1ull * A * B;
			}
		}
		for(int r = 1;r<=n;++r)
			for(int l = r-1;l;--l)
				val[l][r] += val[l+1][r];
		int l,r;
		while(q--){
			read(l),read(r);
			ull ans = 0;
			for(int i = l;i<=r;++i)ans += val[l][i];
			printf("%llu\n",ans);
		}
	}
	#undef N
}

然后看到 \(q \le 5\),说明允许我们每次询问在 \(O(n \log n)\) 时间复杂度内解决问题。统计区间,还带 \(\max\) 的,使用分治。每次 dfs 到一个区间 \([l,r]\),统计经过 \(mid\) 的区间的价值。分类讨论:\(\max a,\max b\) 都在右边/左边的,\(\max a\) 在左/右边 \(\max b\) 在右/左。期望得分 \(52pts\)。

代码

namespace sub2{
	inline bool check(){ return q <= 5; }
	ull al[N],ar[N],bl[N],br[N];
	ull ans;
	void solve(int l,int r){
		if(l > r)return ;
		if(l == r)return ans += a[l] * b[l],void();
		int mid = (l + r) >> 1;
		solve(l,mid),solve(mid+1,r);
		al[mid+1] = bl[mid+1] = 0;
		ar[mid] = br[mid] = 0;
		for(int i = mid;i>=l;--i)
			al[i] = max(al[i+1],a[i]),
			bl[i] = max(bl[i+1],b[i]);
		for(int i = mid+1;i<=r;++i)
			ar[i] = max(ar[i-1],a[i]),
			br[i] = max(br[i-1],b[i]);
		for(int i = mid+1,j = mid+1;i<=r;++i){
			while(j > l && al[j-1] < ar[i] && bl[j-1] < br[i])--j;
			ans += ar[i] * br[i] * (mid+1-j);
		}
		for(int i = mid,j = mid;i>=l;--i){
			while(j < r && al[i] > ar[j+1] && bl[i] > br[j+1])++j;
			ans += al[i] * bl[i] * (j-mid);
		}
		ull sum = 0;
		for(int i = mid,j = mid,k = mid+1;i>=l;--i){
			while(j < r && ar[j+1] < al[i])sum += br[++j];
			while(k <= j && br[k] < bl[i])sum -= br[k++];
			ans += sum * al[i];
		}
		sum = 0;
		for(int i = mid+1,j = mid+1,k = mid;i<=r;++i){
			while(j > l && al[j-1] < ar[i])sum += bl[--j];
			while(k >= j && bl[k] < br[i])sum -= bl[k--];
			ans += sum * ar[i];
		}
	}
	void solve(){
		int l,r;
		while(q--){
			read(l),read(r);
			ans = 0;
			solve(l,r);
			printf("%llu\n",ans);
		}
	}
}

考虑特殊性质:生成的是随机排列。我们定义 \(i\) 向左和向右走,直到遇到第一个比 \(a_i\) 大的位置,得到的区间长度为 \(d_i\)。随机排列的区间长度之和的期望不大,大致在调和级数 \(n \log n\) 级别。详细证明可以看大佬 XuYueming 的博客。那么对于每个 \(a_i\),我们扫描区间 \([la,ra]\) 中的所有位置 \(j\) 对应到 \(b_j\) 及其 \([lb,rb]\)。对于左端点在 \([\max(la_i, lb_j), \min(i, j)]\),右端点在 \([\max(i, j), \min(ra_i, rb_j)]\) 的所有区间价值都为 \(a_i \times b_j\)。我们把左端点和右端点分别作为平面直角坐标系的 \(x\) 轴和 \(y\) 轴,这些区间就是一个矩形,价值和就是矩形的点权和。矩形个数大概是 \(n \log n\) 级别的。我们的 \([l,r]\) 询问就是询问在平面上矩形 \(((l,l),(r,r))\) 内的点权和。扫描线加线段树维护?但是这是一个范围内的多次统计而不是全局的统计。可以使用历史版本和,离线后类似扫描线的方法去扫。这样我写到了 \(84pts\)。

代码

namespace sub3{
	vector qry[N];
	vector<tuple<int,int,ull>> e[N];
ull ans[N];

int la[N],ra[N],lb[N],rb[N];
int st[N],top;
void calc(ull *a,int *L,int *R){
	top = 0; a[n+1] = inf;
	for(int i = 1;i<=n+1;++i){
		while(top && a[st[top]] < a[i])R[st[top--]] = i-1;
		L[i] = st[top] + 1, st[++top] = i;
	}
}
void init(){
	calc(a,la,ra),calc(b,lb,rb);
	for(int i = 1;i<=n;++i){
		for(int j = la[i];j<=ra[i];++j){
			if(rb[j] < i || lb[j] > i)continue;
			pii L (max(la[i],lb[j]), min(i,j));
			pii R (max(i,j), min(ra[i],rb[j]));
			ull val = 1ull * a[i] * b[j];
			e[get<0>(R)].emplace_back(get<0>(L),get<1>(L),val);
			e[get<1>(R)+1].emplace_back(get<0>(L),get<1>(L),-val);
		}
	}
} 

struct Tag{
	ull tag,tagh,tim;
	Tag(){ tag = tagh = tim = 0; }
	Tag(ull _a,ull _b,ull _c):tag(_a),tagh(_b),tim(_c){}
	inline Tag friend operator +(const Tag &a,const Tag &b){
		Tag res = a;
		res.tagh += b.tagh + b.tim * res.tag;
		res.tag += b.tag, res.tim += b.tim;
		return res;
	}
};
struct node{
	int l,r;
	ull sum,sumh;
	inline void pushtag(const Tag &val){
		sumh += val.tagh * (r - l + 1) + sum * val.tim;
		sum += val.tag * (r - l + 1);
	}
};
struct Seg{
	node tr[N << 2];
	Tag tag[N << 2];
	#define ls (p << 1)
	#define rs (p << 1|1)
	#define len(p) (tr[(p)].r-tr[(p)].l+1)
	#define mid ((tr[p].l+tr[p].r)>>1)
	inline void pushup(int p){
		tr[p].sum = tr[ls].sum + tr[rs].sum;
		tr[p].sumh = tr[ls].sumh + tr[rs].sumh;
	}
	inline void pushtag(int p,const Tag &val){
		tr[p].pushtag(val);
		tag[p] = tag[p] + val;	
	}
	inline void pushdown(int p){
		if(!tag[p].tag && !tag[p].tagh && !tag[p].tim)return ;
		pushtag(ls,tag[p]),pushtag(rs,tag[p]);
		tag[p] = Tag();
	}
	void build(int p,int l,int r){
		tr[p] = {l,r,0,0}, tag[p] = Tag();
		if(l == r)return ;
		build(ls,l,mid),build(rs,mid+1,r);
	}
	void modify(int p,int l,int r,const Tag &val){
		if(l <= tr[p].l && tr[p].r <= r)return pushtag(p,val),void();
		pushdown(p);
		if(l <= mid)modify(ls,l,r,val);
		if(mid < r)modify(rs,l,r,val);
		pushup(p);
	}
	ull query(int p,int l,int r){
		if(l <= tr[p].l && tr[p].r <= r)return tr[p].sumh;
		pushdown(p); ull res = 0;
		if(l <= mid)res += query(ls,l,r);
		if(mid < r)res += query(rs,l,r);
		return res;
	}
	#undef len
	#undef mid
	#undef ls
	#undef rs
}seg;
void solve(){
	for(int i = 1,l,r;i<=q;++i){
		read(l),read(r);
		qry[r].emplace_back(l,i);
	}
	init();
	seg.build(1,1,n);
	for(int i = 1;i<=n;++i){
		for(const P &p : e[i])seg.modify(1,get<0>(p),get<1>(p),Tag(get<2>(p),0,0));
		seg.modify(1,1,n,Tag(0,0,1));
		for(const pii &p : qry[i])ans[get<1>(p)] += seg.query(1,get<0>(p),i);
	}
	for(int i = 1;i<=q;++i)printf("%llu\n",ans[i]);
}

}

话说回来,历史版本和如何同时维护两个数的乘积?我们可以考虑使用矩阵先来直观地解剖这个问题。构造结点信息,包含:结点对应区间的长度,\(a_i\) 之和,\(b_i\) 之和,\(a_i \times b_i\) 之和,以及历史 \(a_i \times b_i\) 和。然后构造修改的 Tag 矩阵,用线段树维护矩阵即可。但是这样的做法常数巨大,分数还没有之前的部分分高。

代码

namespace sub4{
	bool S;
	int sta[N],topa;
	int stb[N],topb;
	vector qry[N];
	ull ans[N];
struct Mat{
	int n,m;
	ull c[5][5];
	Mat(){ memset(c,0,sizeof c); }
	Mat(int _n,int _m){ n = _n, m = _m, memset(c,0,sizeof c); }
	Mat(int _n){
		n = m = _n;
		for(int i = 0;i<n;++i)
		for(int j = 0;j<n;++j)
			c[i][j] = (i == j);
	}
	inline void output(){
		puts("-----------");
		for(int i = 0;i<n;++i){
			for(int j = 0;j<m;++j)
				printf("%llu ",c[i][j]);
			puts("");
		}
		puts("-----------");
	}
	inline Mat friend operator *(const Mat &a,const Mat &b){
		Mat res(a.n,b.m); 
		assert(a.m == b.n);
		for(int i = 0;i<res.n;++i)
		for(int j = 0;j<res.m;++j)
		for(int k = 0;k<a.m;++k)
			res[i][j] += a[i][k] * b[k][j];
		return res;
	}
	inline bool friend operator ==(const Mat &a,const Mat &b){
		if((a.n^b.n) || (a.m^b.m))return false;
		for(int i = 0;i<a.n;++i)
		for(int j = 0;j<a.m;++j)
			if(a[i][j] ^ b[i][j])return false;
		return true;
	}
	inline Mat friend operator +(const Mat &a,const Mat &b){
		Mat res(a.n,a.m); assert(a.n == b.n && a.m == b.m);
		for(int i = 0;i<res.n;++i)
		for(int j = 0;j<res.m;++j)
			res[i][j] = a[i][j] + b[i][j];
		return res;
	}
	inline Mat friend operator ^(Mat a,int k){
		Mat res(a.n);
		while(k){
			if(k & 1)res = res * a;
			a = a * a, k >>= 1;
		}
		return res;
	}
	ull* operator [](const int i){ return c[i]; }
	const ull* operator [](const int i)const{ return c[i]; }
}info,mdf,empty;
struct Seg{
	Mat tr[N << 2], tag[N << 2];
	#define ls (p << 1)
	#define rs (p << 1|1)
	#define mid ((l + r) >> 1)
	inline void pushup(int p){ tr[p] = tr[ls] + tr[rs]; }
	void build(int p,int l,int r){
		tr[p] = info, tag[p] = mdf;
		if(l == r)return tr[p][0][0] = 1,void();
		build(ls,l,mid),build(rs,mid+1,r);
		pushup(p);
	}
	inline void pushdown(int p){
		pushtag(ls,tag[p]),pushtag(rs,tag[p]);
		tag[p] = mdf;
	}
	inline void pushtag(int p,const Mat &val){
		tag[p] = tag[p] * val;
		tr[p] = tr[p] * val;
	}
	void modify(int p,int l,int r,int L,int R,const Mat &val){
		if(L <= l && r <= R)return pushtag(p,val);
		pushdown(p);
		if(L <= mid)modify(ls,l,mid,L,R,val);
		if(mid < R)modify(rs,mid+1,r,L,R,val);
		pushup(p);
	}
	ull query(int p,int l,int r,int L,int R){
		if(L <= l && r <= R)return tr[p][0][4];
		ull res = 0; pushdown(p);
		if(L <= mid)res = query(ls,l,mid,L,R);
		if(mid < R)res += query(rs,mid+1,r,L,R);
		return res;
	}
	inline void adda(int l,int r,ull val){
		Mat tmp = mdf;
		tmp[0][1] = tmp[2][3] = val;
		modify(1,1,n,l,r,tmp);
	}
	inline void addb(int l,int r,ull val){
		Mat tmp = mdf;
		tmp[0][2] = tmp[1][3] = val;
		modify(1,1,n,l,r,tmp);
	}
	inline void upd(){
		Mat tmp = mdf;
		tmp[3][4] = 1;
		modify(1,1,n,1,n,tmp);
	}
}seg;
bool T;

void test(){
	// same tag * <=> +
	Mat A = mdf;
	A[0][1] = A[2][3] = 4;
	Mat B = mdf;
	B[0][2] = B[1][3] = 5;	
	Mat C = mdf;
	C[3][4] = 1;
	
	A.output(),C.output();
	
	
	Mat res = (A ^ 3);
	res = res * (B ^ 2);
	res = res * C;
	res = res * (A ^ 6);
	res = res * (B ^ 4);
	res = res * C;
	res.output();
	
	
}
void solve(){
	info = Mat(1,5), mdf = Mat(5), empty = Mat(5,5);
	
	for(int i = 1,l,r;i<=q;++i){
		read(l),read(r);
		qry[r].emplace_back(l,i);
	}
	seg.build(1,1,n);
	for(int i = 1;i<=n;++i){
		while(topa && a[i] > a[sta[topa]])seg.adda(sta[topa-1]+1,sta[topa],-a[sta[topa]]),--topa;
		while(topb && b[i] > b[stb[topb]])seg.addb(stb[topb-1]+1,stb[topb],-b[stb[topb]]),--topb;
		seg.adda(sta[topa]+1,i,a[i]);
		seg.addb(stb[topb]+1,i,b[i]);
		sta[++topa] = i, stb[++topb] = i;
		seg.upd();
		for(const pii &p : qry[i])ans[get<1>(p)] = seg.query(1,1,n,get<0>(p),i);
	}
	for(int i = 1;i<=q;++i)printf("%llu\n",ans[i]);
}

}

矩阵辅助推式子的意义就在于我们可以把矩阵中本质不同的信息提取出来,直接写有用的点的信息转移即可。而找本质不同信息可以多乘几下,就像上面代码中的 test() 函数一样。这样常数较小,离线+单调栈+历史版本和即可。期望分数 \(100pts\)。

代码

/*
推的过程:
info:
0 1 2 3 4
tag:
1 8 5 40 0  
0 1 0 5  0   
0 0 1 8  8   
0 0 0 1  1   
0 0 0 0  1  

1 (0)(1)(2)(3)
0 1 0 (1)(4)
0 0 1 (0)(6)
0 0 0 1 (5)
0 0 0 0 1

merge(info, info):
{0 + 0, 1 + 1, 2 + 2, 3 + 3, 4 + 4}
tag1 * tag2 => res
res[0] = tag1[0] + tag2[0]
res[1] = tag1[1] + tag2[1]
res[2] = tag2[2] + tag1[2] + tag1[0] * tag2[1] + tag1[1] * tag2[0]
res[3] = tag2[3] + tag1[0] * tag2[4] + tag1[1] * tag2[6] + tag1[2] * tag2[5] + tag1[3]
res[4] = tag2[4] + tag1[1] * tag2[5] + tag1[4]
res[5] = tag1[5] + tag2[5]
res[6] = tag1[6] + tag2[6] + tag1[0] * tag2[5]

0 1 2 3 4

merge(info, tag)
res[0] = info[0]
res[1] = info[0] * tag[0] + info[1]
res[2] = info[2] + info[0] * tag[1]
res[3] = info[0] * tag[2] + info[1] * tag[1] + info[2] * tag[0] + info[3]
res[4] = info[0] * tag[3] + info[1] * tag[4] + info[2] * tag[6] + info[3] * tag[5] + info[4]
*/
namespace sub5{
bool S;
int sta[N],topa;
int stb[N],topb;
vector qry[N];
ull ans[N];

struct Tag{
	ull c[7];
	Tag(){ c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = 0; }
	Tag(ull c0,ull c1,ull c2,ull c3,ull c4,ull c5,ull c6){
		c[0] = c0,c[1] = c1,c[2] = c2,c[3] = c3,c[4] = c4,c[5] = c5,c[6] = c6;
	}
	inline Tag friend operator +(const Tag &a,const Tag &b){	
		return Tag(
			a[0] + b[0],
			a[1] + b[1],
			a[2] + b[2] + a[0] * b[1] + a[1] * b[0],
			a[3] + b[3] + a[0] * b[4] + a[1] * b[6] + a[2] * b[5],
			a[4] + b[4] + a[1] * b[5],
			a[5] + b[5],
			a[6] + b[6] + a[0] * b[5]
		);
	}		
	ull & operator [](const int i){ return c[i]; }
	const ull & operator [](const int i)const{ return c[i]; }		
}empty_tag;


struct Info{
	ull c[5];
	Info(){ c[0] = c[1] = c[2] = c[3] = c[4] = 0; }
	Info(ull c0,ull c1,ull c2,ull c3,ull c4){
		c[0] = c0,c[1] = c1,c[2] = c2,c[3] = c3,c[4] = c4;
	}
	inline Info friend operator +(const Info &a,const Info &b){
		return Info(a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3], a[4] + b[4]);
	}
	inline Info friend operator +(const Info &a,const Tag &b){
		return Info(
			a[0],
			a[0] * b[0] + a[1],
			a[2] + a[0] * b[1],
			a[0] * b[2] + a[1] * b[1] + a[2] * b[0] + a[3],
			a[0] * b[3] + a[1] * b[4] + a[2] * b[6] + a[3] * b[5] + a[4]
		);
	}
	ull & operator [](const int i){ return c[i]; }
	const ull & operator [](const int i)const{ return c[i]; }
}empty_info;

struct Seg{
	Info tr[N << 2];
	Tag tag[N << 2];
	#define ls (p << 1)
	#define rs (p << 1|1)
	#define mid ((l + r) >> 1)
	inline void pushup(int p){ tr[p] = tr[ls] + tr[rs]; }
	void build(int p,int l,int r){
		tr[p] = empty_info, tag[p] = empty_tag;
		if(l == r)return tr[p][0] = 1,void();
		build(ls,l,mid),build(rs,mid+1,r);
		pushup(p);
	}
	inline void pushdown(int p){
		pushtag(ls,tag[p]),pushtag(rs,tag[p]);
		tag[p] = Tag();
	}
	inline void pushtag(int p,const Tag &val){
		tag[p] = tag[p] + val;
		tr[p] = tr[p] + val;
	}
	void modify(int p,int l,int r,int L,int R,const Tag &val){
		if(L <= l && r <= R)return pushtag(p,val);
		pushdown(p);
		if(L <= mid)modify(ls,l,mid,L,R,val);
		if(mid < R)modify(rs,mid+1,r,L,R,val);
		pushup(p);
	}
	ull query(int p,int l,int r,int L,int R){
		if(L <= l && r <= R)return tr[p][4];
		ull res = 0; pushdown(p);
		if(L <= mid)res = query(ls,l,mid,L,R);
		if(mid < R)res += query(rs,mid+1,r,L,R);
		return res;
	}
	inline void adda(int l,int r,ull val){
		Tag tmp = empty_tag;
		tmp[0] = val;
		modify(1,1,n,l,r,tmp);
	}
	inline void addb(int l,int r,ull val){
		Tag tmp = empty_tag;
		tmp[1] = val;
		modify(1,1,n,l,r,tmp);
	}
	inline void upd(){
		Tag tmp = empty_tag;
		tmp[5] = 1;
		modify(1,1,n,1,n,tmp);
	}
}seg;
void solve(){
	for(int i = 1,l,r;i<=q;++i){
		read(l),read(r);
		qry[r].emplace_back(l,i);
	}
	seg.build(1,1,n);
	for(int i = 1;i<=n;++i){
		while(topa && a[i] > a[sta[topa]])seg.adda(sta[topa-1]+1,sta[topa],-a[sta[topa]]),--topa;
		while(topb && b[i] > b[stb[topb]])seg.addb(stb[topb-1]+1,stb[topb],-b[stb[topb]]),--topb;
		seg.adda(sta[topa]+1,i,a[i]);
		seg.addb(stb[topb]+1,i,b[i]);
		sta[++topa] = i, stb[++topb] = i;
		seg.upd();
		for(const pii &p : qry[i])ans[get<1>(p)] = seg.query(1,1,n,get<0>(p),i);
	}
	for(int i = 1;i<=q;++i)printf("%llu\n",ans[i]);
}

}

反思

  1. 对于在 \(O(n \log n)\) 时间复杂度内的区间统计,可以使用分治。
  2. 随机排列的一个重要性质:左右区间长度之和的期望大小很小,为 \(n \log n\) 级别。
  3. 对于历史版本和、历史最大值类的推式子,可以先写成矩阵的形式,再简化式子。

标签:Tag,const,比赛,int,res,tag,ull,NOIP2022
From: https://www.cnblogs.com/fight-for-humanity/p/18537198

相关文章

  • 计蒜客:骑车比赛(Dijkstra)
     学习堆优化的写法1#include<bits/stdc++.h>2usingnamespacestd;3intn,m,a,b,c;4typedefpair<int,int>pii;//first表示距离,second表示节点号5vector<pii>graph[1005];6set<pii>minHeap;7vector<int>dis(1005,INT32_MAX);......
  • ctf杂项入门,ctf比赛杂项题型解析
    在CTF(CaptureTheFlag)竞赛中,杂项(Miscellaneous,简称Misc)类题型通常是一组多样化的挑战,涵盖了不属于传统网络安全分类的各种问题。这些题目旨在测试参赛者的广泛技能和知识。题目及答案1.逆向QR码描述:给出一个模糊的QR码。恢复并解码。答案:使用图像处理软件清晰化QR码,然后......
  • 网络安全ctf比赛/学习资源整理,解题工具、比赛时间、解题思路、实战靶场推荐收藏!
    前言对于想学习或者参加CTF比赛的朋友来说,CTF工具、练习靶场必不可少,今天给大家分享自己收藏的CTF资源,希望能对各位有所帮助。CTF在线工具首先给大家推荐我自己常用的3个CTF在线工具网站,内容齐全,收藏备用。1、CTF在线工具箱:http://ctf.ssleye.com/包含CTF比赛中常用的编码......
  • 人工智能是怎么来预测足球比赛结果的?
    在科技日新月异的今天,人工智能已经渗透到我们生活的方方面面,从智能家居到自动驾驶汽车,从虚拟助手到医疗诊断。而现在,AI甚至开始涉足体育领域,尤其是在预测足球比赛结果这一领域展现出了惊人的能力。那么,AI是如何做到预测足球比赛结果的呢?让我们一起揭开这项技术的神秘面纱。......
  • NOIP2022 做题笔记
    由于本人NOIP2023做的太烂了,被教练拉去做NOIP2022了qwqfirsthour:这t1看上去还行,先写了secondhour:t2看上去有些难度,让我想一想thirdhour:快想出来了,先写一写吧fourthhour:写写写写写.....最后100pts遗憾离场......赛后有了深刻的认识,很多题是不能一步到位的,只能拼暴力......
  • 采用 Python 机器学习预测足球比赛结果
    足球是世界上最火爆的运动之一,世界杯期间也往往是球迷们最亢奋的时刻。比赛狂欢季除了炸出了熬夜看球的铁杆粉丝,也让足球竞猜也成了大家茶余饭后最热衷的话题。甚至连原来不怎么看足球的人,也是暗中努力恶补了很多足球相关知识,想通过赛事竞猜先赚一个小目标。今天我们将介绍......
  • AI预测足球比赛结果基于深度数据分析与机器学习SoccerPredictor
    在科技日新月异的今天,人工智能已经渗透到我们生活的方方面面,从智能家居到自动驾驶汽车,从虚拟助手到医疗诊断。而现在,AI甚至开始涉足体育领域,尤其是在预测足球比赛结果这一领域展现出了惊人的能力。那么,AI是如何做到预测足球比赛结果的呢?让我们一起揭开这项技术的神秘面纱。......
  • 人工智能是怎么来预测足球比赛结果的?SoccerPredictor
    在科技日新月异的今天,人工智能已经渗透到我们生活的方方面面,从智能家居到自动驾驶汽车,从虚拟助手到医疗诊断。而现在,AI甚至开始涉足体育领域,尤其是在预测足球比赛结果这一领域展现出了惊人的能力。那么,AI是如何做到预测足球比赛结果的呢?让我们一起揭开这项技术的神秘面纱。......
  • 基于Multisim篮球比赛24S倒计时电路(含仿真和报告)
    【全套资料.zip】篮球比赛24S倒计时电路设计Multisim仿真设计数字电子技术文章目录功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真+报告+讲解视频.zip】功能篮球比赛24S倒计时功能:1.具有数码管显示24S计时功能。2.设置外部开关,可以直接启动......
  • [NOIP2022] 比赛 随机排列 部分分
    看到最大值,考虑使用单调栈搞出\([la_i,ra_i],[lb_i,rb_i]\)表示这一段区间\(i\)是\(a,b\)的最大值。预处理是简单的。inlinevoidinit(){staticautof=[](inta[],intl[],intr[])->void{staticintstack[N],top;top=0,a[n+......