[NOIP2016 普及组] 魔法阵

article/2025/9/27 19:34:11

[NOIP2016 普及组] 魔法阵 - 洛谷


题意分析

给定一个四元组,四个数分别为a,b,c,d,满足以下条件:

1.a<b<c<d

2.b-a=2*(d-c)

3.b-a=(c-b)/3 //注意是实除

现在给你一个序列X,请你求出序列X中每个数分别作为a,b,c,d的个数。

算法一:暴力枚举(PTS 35)

直接进行一个暴力的打,枚举a,b,c,d,判断是否满足条件,再用四个数组分别记录个数。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,m;
int maho[40010];
bool check(int a,int b,int c,int d)
{if(a>=b||b>=c||c>=d) return false;if((b-a)!=2*(d-c)) return false;if(3*(b-a)>=(c-b)) return false;return true;
}
struct node{int aa,bb,cc,dd;
}h[1000010];
int main()
{memset(h,0,sizeof(h));scanf("%d%d",&n,&m);for(int i=1;i<=m;++i){scanf("%d",&maho[i]);}for(int d=1;d<=m;++d){for(int c=1;c<=m;++c){for(int b=1;b<=m;++b){for(int a=1;a<=m;++a){if(check(maho[a],maho[b],maho[c],maho[d])) {h[a].aa++;h[b].bb++;h[c].cc++;h[d].dd++;}}}}}for(int i=1;i<=m;++i){printf("%d %d %d %d\n",h[i].aa,h[i].bb,h[i].cc,h[i].dd);}return 0;
}

时间复杂度:O(n*n*n*n)

ps:这能给35分已经算是施舍了吧。。。

算法二:暴力优化(PTS 55)

不难想到:由a<b<c<d条件可知满足条件的四元组是单调递增的,因此我们不妨现将X排序,减少循环量。(记得记录每个数在原来X序列中的位置,输出时用)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,m;
struct nn{int val,pos;
}maho[40010];
bool check(int a,int b,int c,int d)
{if(a<b&&b<c&&c<d) if((b-a)==2*(d-c)) if((b-a)<(c-b)/3.0) return true;return false;
}
int h[1000010][5];
bool cmp(nn a,nn b)
{if(a.val==b.val) return a.pos < b.pos;else return a.val < b.val;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;++i){scanf("%d",&maho[i].val);maho[i].pos=i;}sort(maho+1,maho+m+1,cmp);for(int a=1;a<=m;++a){for(int b=a+1;b<=m;++b){for(int c=b+1;c<=m;++c){for(int d=c+1;d<=m;++d){if(check(maho[a].val,maho[b].val,maho[c].val,maho[d].val)) {h[maho[a].pos][1]++;h[maho[b].pos][2]++;h[maho[c].pos][3]++;h[maho[d].pos][4]++;}}}}}for(int i=1;i<=m;++i){printf("%d %d %d %d\n",h[i][1],h[i][2],h[i][3],h[i][4]);}return 0;
}

时间复杂度:比纯暴力算法快一点,不过还是O(n*n*n*n)级别的。

ps:蒟蒻在此止步。。。。

算法三:数学计算优化(PTS 100)

毕竟给的三个条件都是一个式子,我们可以活用数学知识来将这三个式子简化。

本题简化的基本思路:用已知数表示未知数

假设t = d - c

则b - a = 2 * t

则c - b >6 * t

所以我们不妨设c - b = 6 * t + k (k > 0)

则此时可以求出:

A点到B点之间的距离为2 * t

B点到C点之间的距离为6 * t + k

C点到D点之间的距离为t

再结合条件一,我们可以得到下面一张简图。

很简陋对吧(技术力低下++)

浅显の分析

到现在大家应该都看出来了应该枚举t并用t表示数。


先弱弱地看一波数据范围。。

 40000......emmmm,看来必须是O(n)的算法了呢~


枚举之前,要先算出各个变量的范围,尽量减少循环数

A的范围:

因为A最小值为1,D最大值为n,且AD=9*t+k;

则A的取值范围:[1,n-9*t-1]

D的范围:

因为AD=9*t+k,且A最小值为1,D最大值为n;

则D的取值范围:[9*t+2,n]

t的范围:

因为D最大为n,且D=A+9*t+1,A最小值为1;

则如果要是有D满足条件,则t满足9*t+2<=n,解得t<n/9;

则t的取值范围:[1,n/9)(此处避免除法,可写作t*9<n)

准备条件妥当,现在还有一个大难题摆在我们面前:如何计算答案?

再分析一下条件:在t一定,且取值范围条件均可满足时,只要满足c-b>6*t,就一定存在四元组,而且只要是满足该条件的所有a,b,c,d,均是四元组。那么若已知该状态下a,b的最大值,那么小于最大值的所有a,b均可形成一个四元组,随着t增大,a,b的最大值相应增大,这时将上个t值时四元组的个数传递下来进行处理,枚举完得到的便是答案。所以,我们可以开四个前缀和数组维护答案。


终焉の代码

分析到这里,也该谈谈代码实现了:

第一层循环:枚举t

没啥好说的。。。

第二层循环:

1.枚举a

枚举a来推b,c,d时,b在a一定的情况下相当于也是定值,那么处理的应是c,d的前缀和,因为c,d均是最大值固定,最小值移动的变量,因此c,d其实要处理的是后缀和,不过我们用倒着枚举a的方式就可以方便地处理后缀和。

for(int A=n-9*t-1;A;A--)
{int B=A+2*t;int D=A+9*t+1;int C=D-t;tem+=sum[C]*sum[D];ans[A][0]+=sum[B]*tem;ans[B][1]+=sum[A]*tem;
}

2.枚举d

与上面同理,只不过因为a,b是最小值固定,最大值移动的变量,所以是正着枚举。

for(int D=9*t+2;D<=n;++D)
{int A=D-9*t-1;int B=A+2*t;int C=D-t;tem+=sum[A]*sum[B];ans[C][2]+=sum[D]*tem;ans[D][3]+=sum[C]*tem;
}

核心代码已经展出,下面是总代码:

/* 1.x[a] < x[b] < x[c]2.x[b] - x[a] = 2 * (x[d] - x[c])3.x[b] - x[a] < (x[c] - x[b]) / 3.0Assumption: t = x[d] - x[c];then: x[b] - x[a] = 2 * t;then: x[c] - x[b] > 6 * t;Assumption: x[c] - x[b] = 6 * t + kso:A -> B: 2 * t;B -> C: 6 * t + k;C -> D: t;so:Range of t: from 1 to n / 9(unequal) Range of A: from 1 to n - 9 * t - 1;Range of D: from 9 * t + 1 + 1 to n;推出以上式子后,枚举t值,便可表示出ABCD的魔法值;再分别枚举A和D,利用乘法原理,算出每个魔法值作为ABCD的次数 
*/
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[40010];
int sum[15010];
int ans[15010][4];
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;++i){scanf("%d",&a[i]);sum[a[i]]++;}for(int t=1;t*9<n;++t){int tem=0;for(int D=9*t+2;D<=n;++D){int A=D-9*t-1;int B=A+2*t;int C=D-t;tem+=sum[A]*sum[B];ans[C][2]+=sum[D]*tem;ans[D][3]+=sum[C]*tem;}tem=0;for(int A=n-9*t-1;A;A--){int B=A+2*t;int D=A+9*t+1;int C=D-t;tem+=sum[C]*sum[D];ans[A][0]+=sum[B]*tem;ans[B][1]+=sum[A]*tem;}}for(int i=1;i<=m;++i){printf("%d %d %d %d\n",ans[a[i]][0],ans[a[i]][1],ans[a[i]][2],ans[a[i]][3]);}return 0;
}

时间复杂度:差不多O(n)(我真不会算)

后记:

1.帮不是很懂为什么要乘tem的童鞋解释一下: 乘法原理_百度百科

2. 如果文章中有地方与代码有出入,请以代码为准,毕竟程序一定不会骗人


http://chatgpt.dhexx.cn/article/kkYwLeIG.shtml

相关文章

NOIP 2016 普及组

文章目录 T1 买铅笔T1分析 T2 回文日期T2分析 T3 海港T3分析 T4 魔法阵T4分析 T1 买铅笔 题目点击→计蒜客 [NOIP2016]买铅笔 题目描述 P 老师需要去商店买 n n n 支铅笔作为小朋友们参加 NOIP 的礼物。她发现商店一共有 3 3 3 种包装的铅笔&#xff0c;不同包装内的铅笔数…

题解 【NOIP2016】魔法阵

【NOIP2016】魔法阵 Description 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法量。 大魔法师有m个魔法物品,编号分别为1,2,...,m。每个物品具有一个魔法值,我们用xi表示编号为i的物品的魔法值。每个魔法值xi是不超过n的正整数,可能有多个物品的魔…

NOIP2016总结

Day1&#xff1a; T1&#xff1a;模拟&#xff1b; 1 #include<iostream>2 #include<cstdio>3 #include<cstdlib>4 #include<cstring>5 #include<string>6 #include<ctime>7 #include<cmath>8 #include<set>9 #include<map…

2016noip-问题求解超级详细解

noip2016普及组问题求解 从一个44的棋盘&#xff08;不可旋转&#xff09;中选取不在同一行也不在同一列上的两个方格&#xff0c;共有&#xff08; &#xff09;种方法。 解题&#xff1a;首先是如下棋盘 于是我们发现这是组合问题&#xff0c;也就是从16个格子中选择两个格子…

MIPI D-PHY C-PHY

MIPI可分为物理层和逻辑层两大部分。物理层尽可能采用通用内容&#xff0c;逻辑层则是分别面向摄像头、显示屏、移动通信、存储等不同用途的专用协议。MIPI的物理层有D-PHY、M-PHY、C-PHY等3种。D-PHY现在大量应用于应用处理器与显示屏、摄像头连接的部分。随着摄像头、显示屏的…

以太网phy学习

关键词 10BASE2:采用细同轴电缆接口的IEEE 802.3 10Mb/s物理层规格(参见IEEE 802.3 Clause 10.) 10BASE5:采用粗同轴电缆接口的IEEE 802.3 10Mb/s物理层规格(参见IEEE 802.3 Clause 8.) 10BASE-F:采用光纤电缆接口的IEEE 802.3 10Mb/s物理层规格(参见IEEE 802.3 Clause 15.) 1…

M-PHY协议解读一:M-PHY整体概述

1.1 M-PHY整体概述 M-PHY协议思维导图如下&#xff1a; 思维导图主要分为两大部分&#xff1a;M-PHY基本特点和基本概念。第一部分对M-PHY的基本特点进行描述&#xff0c;通过与D-PHY/C-PHY多个维度的对比分析&#xff0c;对M-PHY有一个整体的基本认识&#xff1b;第二部分对M…

以太网PHY 开发与解析

目录 1.PHY芯片介绍 1.1 芯片引脚定义和说明 1.2 PHY芯片功能说明 1.3 供电管理 1.4 寄存器说明 1.4.1 控制寄存器 1.4.2 状态寄存器 1.4.3 PHY ID寄存器 1.4.4 自协商广播寄存器 1.4.5 自动协商链接合作伙伴能力寄存器 1.4.6 自动协商扩展寄存器 1.4.7 AVICOM指定…

PHY MAC

常用网卡芯片 DM9000 MAC(数据链路层)PHY(物理层) CS8900 PHY LAN91C111 MACPHY PHY 百科名片 PHY指物理层&#xff0c;OSI的最底层。 一般指与外部信号接口的芯片。 以太网PHY芯片 。小小的不起眼但又无处不在的网卡。如果在5年前&#xff0…

MIPI C-PHY 与 D-PHY

MIPI&#xff1a;即移动产业处理器接口&#xff08;Mobile Industry Processor Interface 简称MIPI&#xff09;联盟&#xff1b;是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。 CSI&#xff1a;MIPI-CSI-2协议是MIPI联盟协议的子协议&#xff0c;专门针对摄像头…

MIPI系列之“C-PHY”

本篇主要介绍物理层WG中的C-PHY。C-PHY基于3-Phase symbol编码技术&#xff0c;通过three-wire trios传输2.28 bits/symbol&#xff0c;其目标速率是2.5Gsymbols/s。C-PHY与D-PHY有许多共同点&#xff0c;C-PHY的绝大部分特性都是从D-PHY改编而来的。C-PHY被设计成能够与D-PHY在…

ethernet phy

phy处于physical层&#xff0c;上一层是data link层&#xff1a;MAC&#xff0c;两者通过xMII和MDIO接口通信。 xMII XMII包含MII(802.3 sec22&#xff0c;适用于10M和100M传输)&#xff0c;GMII(802.3 sec35.2.2&#xff0c;适用于1000M传输)&#xff0c;RGMII(GMII的简化版)…

USB的PHY

Linux USB 3.0驱动分析&#xff08;六&#xff09;——USB主机控制器HCD分析 网卡芯片,也有 controller(mac芯片) 和 PHY部分 USB 芯片,也有 controller 和 PHY部分 5G 芯片,也有 协议层 和 PHY部分USB主机控制器和USB PHY是如何完成收发数据的 USB 全套硬件组成ControllerC…

PHY芯片

以太网媒体接入控制器(MAC) 物理接口收发器(PHY) 以太网接口可分为协议层和物理层。 协议层是由一个叫MAC(Media Access Layer&#xff0c;媒体访问层)控制器的单一模块实现。 物理层由两部分组成&#xff0c;即PHY(Physical Layer&#xff0c;物理层)和传输器。 常见的网卡芯片…

C-PHY技术是什么

2018年5月17日&#xff0c;一加发布了自家旗舰手机一加6&#xff0c;在相机的宣传图片中&#xff0c;首次见到提起C-PHY技术和Type-2对焦这两个概念&#xff0c;于是经过在网络的挖掘和学习&#xff0c;先总结下C-PHY技术的基本概念 C-PHY技术来自哪里 图像传感器&#xff0c;…

MIPI 系列之 D-PHY

目录 1、简述 2、管脚连接 3、D-PHY 的时钟 4、D-PHY Lane (Clock Lane And Data Lane) 4.1、信号摆幅 4.2、信号含义 4.3、状态码 5、传输特性和方向 6、D-PHY Data Lane 6.1、高速 Data Lane 传输 6.2、双向传输 Data Lane Turnaround 6.3、Data Lane 的 Escape …

PHY- PHY芯片概述

1 PHY概述 关于Internet Protocal的分层模型可以参考文章 :【Internet Protocal-OSI模型中的网络分层模型】,下面我们讲讲底层以太网控制器和收发器的知识。其主要是处理OSI模型中的物理层和链路层的事情。 在CAN/CANFD、FlexRay等总线中,有控制器Controller和收发器Transc…

以太网PHY原理介绍

一、以太网分层模型 基于 OSI 七层网络模型&#xff0c; 车载以太网的网络拓扑结构如图1-1所示。 图1-1 车载以太网网络拓扑结构图 从图中可以看到位于 Layer1 和 Layer2 的为物理层和数据链路层。 Layer3 以上各层包含了 TCP/IP、 DOIP、SomeIP 等协议&#xff0c; 由 EthSt…

PHY(Physical Layer,PHY)通俗理解

碎碎念&#xff1a;最近更新的周期有点长... 主要最近和朋友一起重新开了一个公众号&#xff08;FPGA Breaker&#xff09;&#xff0c;这个公众号也和本公众号垂直深度&#xff0c;不会和本公众号内容有太多重叠&#xff0c;主要是本人想推进国内开源IP的使用和发展&#xff0…

MAC和PHY的区别

&#xfeff;&#xfeff; 转载自&#xff1a;https://www.cnblogs.com/feitian629/archive/2013/01/25/2876857.html 一块以太网网卡包括OSI&#xff08;开方系统互联&#xff09;模型的两个层。物理层和数据链路层。物理层定义了数据传送与接收所需要的电与光信号、线路状态、…