当前位置: 首页 > news >正文

P2119 [NOIP 2016 普及组] 魔法阵

P2119 [NOIP 2016 普及组] 魔法阵

题目背景

NOIP2016 普及组 T4

题目描述

六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量。

大魔法师有 mmm 个魔法物品,编号分别为 1,2,…,m1,2,\ldots,m1,2,,m。每个物品具有一个魔法值,我们用 XiX_iXi 表示编号为 iii 的物品的魔法值。每个魔法值 XiX_iXi 是不超过 nnn 的正整数,可能有多个物品的魔法值相同。

大魔法师认为,当且仅当四个编号为 a,b,c,da,b,c,da,b,c,d 的魔法物品满足 Xa<Xb<Xc<Xd,Xb−Xa=2(Xd−Xc)X_a<X_b<X_c<X_d,X_b-X_a=2(X_d-X_c)Xa<Xb<Xc<Xd,XbXa=2(XdXc),并且 Xb−Xa<(Xc−Xb)/3X_b-X_a<(X_c-X_b)/3XbXa<(XcXb)/3 时,这四个魔法物品形成了一个魔法阵,他称这四个魔法物品分别为这个魔法阵的 AAA 物品,BBB 物品,CCC 物品,DDD 物品。

现在,大魔法师想要知道,对于每个魔法物品,作为某个魔法阵的 AAA 物品出现的次数,作为 BBB 物品的次数,作为 CCC 物品的次数,和作为 DDD 物品的次数。

输入格式

第一行包含两个空格隔开的正整数 n,mn,mn,m

接下来 mmm 行,每行一个正整数,第 i+1i+1i+1 行的正整数表示 XiX_iXi,即编号为 iii 的物品的魔法值。

保证 1≤n≤150001 \le n \le 150001n150001≤m≤400001 \le m \le 400001m400001≤Xi≤n1 \le X_i \le n1Xin。每个 XiX_iXi 是分别在合法范围内等概率随机生成的。

输出格式

mmm 行,每行 444 个整数。第 iii 行的 444 个整数依次表示编号为 iii 的物品作 为 A,B,C,DA,B,C,DA,B,C,D 物品分别出现的次数。

保证标准输出中的每个数都不会超过 10910^9109。每行相邻的两个数之间用恰好一个空格隔开。

输入输出样例 #1

输入 #1

30 8
1
24
7
28
5
29
26
24

输出 #1

4 0 0 0
0 0 1 0
0 2 0 0
0 0 1 1
1 3 0 0
0 0 0 2
0 0 2 2
0 0 1 0

输入输出样例 #2

输入 #2

15 15
1 
2 
3 
4 
5
6 
7 
8 
9
10
11
12
13
14
15

输出 #2

5 0 0 0
4 0 0 0
3 5 0 0
2 4 0 0
1 3 0 0
0 2 0 0
0 1 0 0
0 0 0 0
0 0 0 0
0 0 1 0
0 0 2 1
0 0 3 2
0 0 4 3
0 0 5 4
0 0 0 5

说明/提示

【样例解释 111

共有 555 个魔法阵,分别为:

  • 物品 1,3,7,61,3,7,61,3,7,6,其魔法值分别为 1,7,26,291,7,26,291,7,26,29
  • 物品 1,5,2,71,5,2,71,5,2,7,其魔法值分别为 1,5,24,261,5,24,261,5,24,26
  • 物品 1,5,7,41,5,7,41,5,7,4,其魔法值分别为 1,5,26,281,5,26,281,5,26,28
  • 物品 1,5,8,71,5,8,71,5,8,7,其魔法值分别为 1,5,24,261,5,24,261,5,24,26
  • 物品 5,3,4,65,3,4,65,3,4,6,其魔法值分别为 5,7,28,295,7,28,295,7,28,29

以物品 555 为例,它作为 AAA 物品出现了 111 次,作为 BBB 物品出现了 333 次,没有作为 CCC 物品或者 DDD 物品出现,所以这一行输出的四个数依次为 1,3,0,01,3,0,01,3,0,0

此外,如果我们将输出看作一个 mmm444 列的矩阵,那么每一列上的 mmm 个数之和都应等于魔法阵的总数。所以,如果你的输出不满足这个性质,那么这个输出一定不正确。你可以通过这个性质在一定程度上检查你的输出的正确性。

【数据规模】

70分

排序,
四次循环(用给的等式剪枝)
排序
输出

#include <bits/stdc++.h>
using namespace std;
const int N=4e4+5;
struct node{int id,v,m[5];node(){memset(m,0,sizeof(m));};node(int idx,int vx){id=idx,v=vx;memset(m,0,sizeof(m));};bool operator<(const node& x)const{if(v==x.v)return id<x.id;else return v<x.v;}//const &避免拷贝,直接操作原元素,还不能修改 
}obj[N];
bool cmp(const node& a,const node& b){return a.id<b.id;}
int n,m;
void view(){cout<<"显示各物质"<<endl;for(int i=1;i<=m;i++)cout<<obj[i].id<<"\t";cout<<endl;for(int i=1;i<=m;i++)cout<<obj[i].v<<"\t";cout<<endl;
}
void view2(){//cout<<"显示各次数"<<endl;for(int i=1;i<=m;i++){for(int j=1;j<=4;j++)cout<<obj[i].m[j]<<" ";cout<<endl;}}	
int main(){//freopen("data.cpp","r",stdin);cin>>n>>m;for(int i=1;i<=m;i++){int x;cin>>x;obj[i]=node(i,x);}//view();sort(obj+1,obj+m+1);//view();/*a<b<c<db-a<(c-b)/3b-a=2*(d-c)*/for(int i1=1;i1<=m;i1++)for(int i2=i1+1;i2<=m;i2++){if(obj[i2].v==obj[i1].v)continue;if((obj[i2].v-obj[i1].v)%2)continue;for(int i3=i2+1;i3<=m;i3++){//if((obj[i3].v-obj[i2].v)%3)continue;没说等于,所以不能被3整除也可以 if(obj[i2].v==obj[i3].v)continue;if((obj[i2].v-obj[i1].v)*3>=(obj[i3].v-obj[i2].v))continue;for(int i4=i3+1;i4<=m;i4++){if(obj[i4].v==obj[i3].v)continue;if(obj[i2].v-obj[i1].v!=2*(obj[i4].v-obj[i3].v))continue;obj[i1].m[1]++; obj[i2].m[2]++; obj[i3].m[3]++; obj[i4].m[4]++; }}}sort(obj+1,obj+m+1,cmp);//view();view2();return 0;
}

学习洛谷题解100分

等式分析转换观察作图掌握规律
发现是ab和cd分别一一对应,
ab对应众多众多cd,而且随着a的减少对应cd线性增加,可以后缀和
cd对应众多ab,随着d增加ab也会增加,前缀和。
厉害,前缀和有用。

#include <bits/stdc++.h>
using namespace std;
const int N=15000,//数值极限 M=40001;//数字数量的极限,不能写成4e4=40000 
int n,//数字的上限 m,//数的数量v[M],//每个数的数值cnt[N],//每个数出现的次数 A[N],B[N],C[N],D[N];//每个数成为abcd组合的次数 
int main(){//freopen("data.cpp","r",stdin);cin>>n>>m;for(int i=1;i<=m;i++){cin>>v[i];cnt[v[i]]++;}//每个数,还有每个数出现的次数 /*已知a<b<c<d,b-a=2(d-c),	b-a<(c-b)/3设t=d-c于是b-a=2*t根据b-a<(c-b)/3,变成3*(b-a)<c-b,再变成6t<c-b,所以c-b=6t+k(变数k可以从1逐个变大,限制于极限n) 结论:数轴里1到极限n的线段中能找到a、b、c、d四个位置a(	间隔2t	)b(	间隔6t+k(从1到整体限制的变数)	)c(	间隔t	)dt在极限n(9t+1<=n)范围内可大可小a从最大(n-9t-1)减小到1,每次都会有唯一对应的b=a+2t也有对应的c=b+6t+1(k最小=1时),和d=c+t但是,因着k的增加,同样的ab有很多cd,这个没有当时体现,在a减小过程中逐渐增多 所以在a变化过程中生成的cd数要累加(后缀和),不仅仅可以和现在的ab组合,还要和往后的ab组合这里算了ab出现的次数 d从最小(9t+2)增加到n,每次有唯一对应c=d-tk时1是对应的b=c-6t-1(k最小=1),a=b-2t同样随着d的增加会有不同的ab,这些其实也是每对cd因不同k所得,要累加这次循环只算了cd次数 */for(int t=1;9*t+1<=n;t++){//最大的数n起码能分成九分,还多个最小的k int a,b,c,d,//四个数sum=0;//前缀和,随着d的增加对应的ab逐渐增加(其实是同一对cd因k会有很多对应的ab) for(d=9*t+2;d<=n;d++){//随着d的增加k也增加。最小的d:a从1开始+9t+最小的k=9t+2。 c=d-t;//d生成唯一c a=d-9*t-1,b=a+2*t,//相对于d生成最小的a(a生成b),此时k=1,随着d的增加会得到不同k对应的ab(需要前缀和) sum+=cnt[a]*cnt[b];//几个a几个b形成多种组合。前缀和,要累加。跟后面的c、d(其实就是k不同)都可以组合 //a(2t)ba(2t)ba(2t)ba(2t)b……a(2t)b(6t+1)c(t)d,这个cd有很多对应的ab,d增加,前序会变多 C[c]+=sum*cnt[d],D[d]+=sum*cnt[c];//这里只算了c、d的,没有算a、b}sum=0;for(int a=n-9*t-1;a>=1;a--){//a数值要逐渐减小,怎样后序cd数量会增加。 b=a+2*t;//a生成唯一b c=b+6*t+1,d=c+t;//相对于b得到k=1最小时的c(c生成唯一d),随着a的增加可以得到很多k变化后的cd,前缀和 sum+=cnt[c]*cnt[d];//相对于变化的a(a生成唯一b)生成不同k的c、d,这些c、d要累加,作用到后面的a、b//a(2t)b(6t+1)c(t)d……c(t)dc(t)dc(t)dc(t)d,没对ab都有很多对应的cd,a值减小,后继会变多 A[a]+=sum*cnt[b],B[b]+=sum*cnt[a]; //这里只算了a、b的,没有重复算c、d}}//view();for(int i=1;i<=m;i++){cout<<A[v[i]]<<" "<<B[v[i]]<<" "<<C[v[i]]<<" "<<D[v[i]]<<endl;//每个数分别充当a、b、c、d的次数 }return 0;
}
http://www.dtcms.com/a/528006.html

相关文章:

  • 数据结构13:排序
  • 网站搭建 里短信wordpress acf破解版
  • 【C/C++】数据在内存中的存储
  • 我们项目中如何运用vueuse
  • 【开发者导航】集成多引擎与离线查询的macOS开源翻译工具:Easydict
  • 龙岗客户 IBM x3650 M5服务器system board fault故障,上门快修分享
  • TENGJUN-TYPE-C 24PIN(JX24-BPS015-A)连接器深度技术解析
  • 10.23作业
  • 深入剖析 Vue Router History 路由刷新页面 404 问题:原因与解决之道
  • FreeP2W:一个PDF转Word的CLI工具
  • .NET - .NET Aspire的Command-Line和GitHub Copilot
  • 10月25日
  • 【电玩电脑杂志】超级整理合集PDF
  • 怎样做某个网站有更新的提醒成都网络优化网站
  • 计算机视觉:python车牌识别检测系统 YOLOv8 深度学习pytorch技术 LPRNet车牌识别算法 CCPD2020数据集 ✅
  • Qt 中如何操作 Excel 表格:主流开源库说明介绍与 QXlsx 库应用全解析
  • 基于单片机的全自动洗衣机控制器设计
  • 电子商务网站规划原则教师遭网课入侵直播录屏曝光口
  • 免费发广告网站攀枝花建设集团网站
  • Day 23 机器学习管道 pipeline
  • Vue CLI 插件开发完全指南:从原理到实战
  • Linux中内核和用户空间通信send_uevent函数的实现
  • Python设计模式实战:用Pythonic的方式实现单例、工厂模式
  • 智能规模效应:解读ChatGPT Atlas背后的数据边界之战
  • 网站建设雨点国家防疫政策最新
  • RabbitMQ Unacked 消息深度解析:机制、问题与解决方案
  • LabVIEW超高温高压流变仪开发
  • 理解面向问题域的需求分析(PDOA)方法
  • 肥东住房和城乡建设部网站WordPress国外赚钱
  • Dify从入门到精通 第31天 在 Dify 中构建智能天气查询机器人