2020.9.13 NOIP模拟赛4 T3 XOR

博客介绍了如何利用01 trie数据结构解决数对低bit(A[i], A[j])之和的问题。通过建立01 trie树,计算数列中所有数对的公共前缀长度,进而求得lowbit之和,答案对199907210507取模。题目要求1<=n<=105, 1<=A[i]<=2^60-1,文章提供了解题思路及代码实现。" 126742029,15292924,链表在Java开发中的应用实践,"['数据结构', '链表', 'Java开发', '算法应用']

题目描述:给定一个数列{AnA_nAn},考虑所有数对(i,j)(i,j)(i,j)(i∈[1,n],j∈[1,n])(i\in[1,n],j\in[1,n])(i[1,n],j[1,n]),求所有的lowbit(A[i],A[j])lowbit(A[i],A[j])lowbit(A[i],A[j])之和
答案对199907210507199907210507199907210507取模

输入格式:第一行一个整数nnn
---------------第二行nnn个整数,代表AAA数组

输出格式:一个数,所有的lowbit(A[i],A[j])lowbit(A[i],A[j])lowbit(A[i],A[j])之和

数据范围:1<=n<=1051 <= n <= 10^51<=n<=105
 1<=A[i]<=260−1\quad\quad\quad\quad \ 1<=A[i] <=2^{60}-1 1<=A[i]<=2601

考虑到lowbit(A[i],A[j])lowbit(A[i],A[j])lowbit(A[i],A[j])的含义为A[i],A[j]A[i],A[j]A[i],A[j]二进制拆分下的最小一位不同的位置所代表的不同的二进制数, (考后听同学讲述了01trie01trie01trie之后) ,等价于他们有一段公共前缀,就可以自然而然地想到01trie01trie01trie

tiretiretire,每个数从低位到高位插入,这一位是000就进入该树的左子树,否则进入右子树,记住每一个数都要有606060长度,高位补000,否则不好计数

nnn代表A[i],A[j]A[i],A[j]A[i],A[j]trietrietrie的公共前缀的长度
建好树后,因为lowbit(A[i],A[j])lowbit(A[i],A[j])lowbit(A[i],A[j])等于2n2^n2ndfs trie树dfs \ trie树dfs trie,对于每一个节点,ansansans加上 左子树的个数与右子树个数和2n2^n2n(nnn为深度)这三个数的乘积即可
这也是为什么每个数插入的时候都要高位补000

(trietrietrie在解决这种带有公共前缀的问题有奇用)

CodeCodeCode

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 1e5, Mod = 199907210507;
int a[MAXN + 10];
int tree[MAXN * 70 + 10][2], size[MAXN * 70 + 10], rt = 0, tot = 0, ans = 0;
inline int read();

namespace subtask1{
	inline int lowbit(int x){return x&(-x);}
	void Main(int n){
		int ans = 0;
		for (register int i = 1; i <= n; ++i)
			for (register int j = i + 1; j <= n; ++j)
				ans = (ans + 2 * lowbit(a[i]^ a[j])) % Mod;
		printf("%lld\n",ans);
	}
}

void dfs(int x, int sum){
	if (tree[x][0] != -1)	dfs(tree[x][0], sum * 2 % Mod);
	if (tree[x][1] != -1)	dfs(tree[x][1], sum * 2 % Mod);
	if (tree[x][0] < 0)	tree[x][0] = tot + 1;
	if (tree[x][1] < 0) tree[x][1] = tot + 1;
	ans = (ans + size[tree[x][0]] * sum % Mod * size[tree[x][1]] % Mod) % Mod;
	size[x] += size[tree[x][0]] + size[tree[x][1]];
}


signed main(){
	freopen ("xor.in","r",stdin);
	freopen ("xor.out","w",stdout);
	memset(tree, -1 ,sizeof(tree));
	int n = read(), mx = 0;
	for (register int i = 1; i <= n; ++i){
		a[i]= read();
		mx = max(mx, a[i]);
	}
	if (n <= 200){
		subtask1::Main(n);
		return 0;
	}
	for (register int i = 1; i <= n; ++i){
		int now = rt;
		for (register int j = 1; j <= mx; j = j * 2){
			int x = (a[i] & j) ? 1 : 0;
			if (tree[now][x] == -1)	tree[now][x] = ++tot;
			now = tree[now][x];
		}
		++size[now];
	}
	dfs(0, 1);
	printf("%lld\n", ans * 2 % Mod);
	return 0;
}

inline int read(){
	int x = 0;
	char c = getchar();
	while (!isdigit(c))c = getchar();
	while (isdigit(c))x = (x << 1) + (x << 3) + (c & 15), c = getchar();
	return x;
}
内容概要:本文围绕可变桨叶四旋翼无人机的规范控制与点对点运动模拟展开,重点研究优化推力分配策略在翻转动作中的应用与性能比较。通过Matlab代码实现,构建了四旋翼动力学模型,并设计了多种控制算法以实现精确的姿态调整与轨迹跟踪。研究对比了不同推力分配方案在执行高机动性翻转动作时的稳定性、能耗效率与响应速度,旨在提升无人机在复杂飞行任务中的动态性能与控制精度。该仿真研究为无人机飞控系统的设计与优化提供了理论依据和技术支持。; 适合人群:具备一定自动控制理论基础和Matlab编程能力,从事无人机控制、飞行器动力学或机器人系统研究的科研人员及研究生。; 使用场景及目标:① 实现四旋翼无人机在三维空间中的精确点对点运动控制;② 对比分析不同推力分配策略在执行翻转等高难度动作时的控制效果与能耗表现,优化飞行性能;③ 为无人机自主飞行、特技飞行及复杂环境下的机动控制提供算法验证平台。; 阅读建议:此资源以Matlab仿真为核心,建议读者结合相关控制理论知识,深入理解代码实现细节,重点关注动力学建模、控制律设计与推力分配模块。在学习过程中,应动手调试参,复现文中翻转动作的仿真结果,并尝试拓展至其他复杂飞行任务,以加深对无人机控制机理的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值