Noip整理
- 格式:doc
- 大小:80.50 KB
- 文档页数:8
描述fibonacci数列From adminDescription著名的斐波那契数列f[n]=1 n=1,2f[n-1]+f[n-2] n>2现在求第n项,由于f[n]可能很大,你只需要输出mod 32768的值即可。
输入格式 InputFormat仅有一行,为n,1<=n<=maxlongint输出格式 OutputFormat仅有一个数字,即答案样例输入 SampleInput3样例输出 SampleOutput2Flag Accepted 题号P1337模式Normal(OI)内存限制128MB 代码限制64KB类型(?)数论/ 数值值数论/数值通过675人提交1579次通过率43%难度 3矩阵的快速幂是用来高效地计算矩阵的高次方的。
将朴素的o(n)的时间复杂度,降到log(n)。
原理:一般一个矩阵的n次方,我们会通过连乘n-1次来得到它的n次幂。
但做下简单的改进就能减少连乘的次数,方法如下:把n个矩阵进行两两分组,比如:A*A*A*A*A*A => (A*A)*(A*A)*(A*A)这样变的好处是,你只需要计算一次A*A,然后将结果(A*A)连乘自己两次就能得到A^6,即(A*A)^3=A^6。
算一下发现这次一共乘了3次,少于原来的5次。
其实还可以取A^3作为一个基本单位。
原理都一样:利用矩阵乘法的结合律,来减少重复计算的次数。
以上都是取一个具体的数来作为最小单位的长度,这样做虽然能够改进效率,但缺陷也是很明显的,取个极限的例子(可能有点不恰当,但基本能说明问题),当n无穷大的时候,现在所取的长度其实和1没什么区别。
所以就需要我们找到一种与n增长速度”相适应“的”单位长度,这点是我们要思考的问题。
既然要减少重复计算,那么就要充分利用现有的计算结果,怎么充分利用计算结果呢?这里考虑二分的思想。
比如A^19 => (A^16)*(A^2)*(A^1),显然采取这样的方式计算时因子数将是log(n)级别的(原来的因子数是n),不仅这样,因子间也是存在某种联系的,比如A^4能通过(A^2)*(A^2)得到,A^8又能通过(A^4)*(A^4)得到,这点也充分利用了现有的结果作为有利条件。
●计算机语言计算机语言通常是一个能完整、准确和规则地表达人们的意图,并用以指挥或控制计算机工作的“符号系统”。
计算机语言通常分为三类:即机器语言,汇编语言和高级语言。
1、机器语言是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。
它是计算机的设计者通过计算机的硬件结构赋予计算机的操作功能。
机器语言具有灵活、直接执行和速度快等特点。
2、为了克服机器语言难读、难编、难记和易出错的缺点,人们就用与代码指令实际含义相近的英文缩写词、字母和数字等符号来取代指令代码(如用ADD表示运算符号“+”的机器代码),于是就产生了汇编语言。
所以说,汇编语言是一种用助记符表示的仍然面向机器的计算机语言。
汇编语言亦称符号语言。
3、高级语言是面向用户的语言。
无论何种机型的计算机, 只要配备上相应的高级语言的编译或解释程序,则用该高级语言编写的程序就可以通用。
目前被广泛使用的高级语言有BASIC、PASCAL、C、COBOL、FORTRAN、LOGO 以及VC、VB等。
这些语言都是属于系统软件。
●计算机的主要性能指标1. 字长:在同一时间中处理二进制数的位数叫字长。
早期的微机字长一般是8位和16位,386以及更高的处理器大多是32位。
目前市面上的计算机的处理器大部分已达到64位。
2. 速度3. 存储系统容量(bit,B,KB,MB,GB,TB) 1B=8bit 1KB=1024B1MB(兆字节)=1024KB 1GB(兆兆字节)=1024MB 1TB=1024GB●计算机软件a、BIOS:"基本输入输出系统"。
其实,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、系统设置信息、开机后自检程序和系统自启动程序。
其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。
解释程序:高级语言翻译的一种,它将源语言(如basic)书写的源程序作为输入,解释一句后就提交计算机执行一句,并不形成目标程序.翻译程序: (编译程序)一类很重要的语言处理程序,它把高级语言(如FORTRAN,COBOL,pascal,c等)源程序作为输入,进行翻译转换,产生出机器语言的目标程序,然后再让计算机去执行这个目标程序,得到计算结果.语言:机器语言汇编语言高级语言(面向对象,面向过程)数据库管理软件:Foxpro,Access,Orale,Sybase,DB2和Informix等。
NOIP初赛知识点复习知识点一:基本数据结构和算法1.数组:特点是连续存储数据,根据索引可以快速访问元素。
2.链表:特点是每个节点包含一个元素和指向下一个节点的指针,可以实现动态插入和删除元素。
3.栈:先进后出(FILO)的数据结构,常用于解决递归问题和表达式求值。
4.队列:先进先出(FIFO)的数据结构,常用于模拟系统等需要先后顺序的场景。
5.树:包括二叉树、二叉树、平衡二叉树等,常用于实现、排序、哈希等算法。
6.图:由节点和边组成的数据结构,常用于解决网络、路径等相关问题。
7.排序算法:包括冒泡排序、插入排序、选择排序、快速排序、归并排序等。
8.查找算法:包括线性查找、二分查找、哈希查找等。
知识点二:计算机基础知识1.数据类型:包括整型、浮点型、字符型等,了解不同数据类型在内存中的表示方式。
2.进制转换:了解二进制、十进制、十六进制之间的转换原理和方法。
3.编程语言:了解至少一种编程语言的基本语法和常见数据结构的实现方式。
4.操作系统:了解操作系统的基本原理和常见命令,如进程管理、文件系统、内存管理等。
5.计算机网络:了解常见的网络协议和网络通信的基本原理。
6.数据库:了解数据库的基本概念和常用的数据库管理系统。
7. 前端开发:了解HTML、CSS、JavaScript等前端开发技术和框架。
知识点三:动态规划1.动态规划的基本思想和步骤:确定状态、状态转移方程、初始条件和边界条件、计算顺序。
2.最长递增子序列(LIS)问题:求一个序列中最长的递增子序列的长度。
3.最大连续子序列和问题:求一个序列中和最大的连续子序列的和。
4.背包问题:给定一组物品和一个背包的容量,求在不超过背包容量的情况下能够装入的物品的最大价值。
知识点四:图论和算法1.图的遍历:包括深度优先(DFS)和广度优先(BFS)。
2.最短路径问题:包括狄克斯特拉算法和弗洛伊德算法。
3.拓扑排序:针对有向无环图(DAG)进行排序的算法。
NOIP复赛基础知识汇总(cxms)(一) Math库实用汇总 (1)(二) T urbo Pascal过程与函数调用 (3)(三) 排序(快排、冒泡、堆排): (6)(四) 常用数据类型 (7)(五) 高精度 (7)(六) 常用算法 (12)(七) 普通树的遍历 (13)(八) 二叉树 (13)(九) 数论相关算法 (17)(十) 排列组合 (19)(十一) 图论 (21)(一)Math库实用汇总使用方法:在程序头用Uses语句加载Math库例子:Program Ex_Math;Uses Math;BeginWriteln(hypot(3,4));End.函数介绍:hypot原型:function hypot(x:float;y:float):float功能:返回直角三角形中较长边的长度,也就是sqrt(sqr(x)+sqr(y))ceil原型:function ceil(x:float):Integer功能:返回比参数大的最小整数引发错误:在x超出Integer的范围时会引发溢出错误floor原型:function floor(x:float):Integer功能:返回比参数小的最大整数引发错误:在x超出Integer的范围时会引发溢出错误power原型:function power(base:float;exponent:float):float功能:返回base的exponent次方引发错误:在base为负数且exponent为小数时intpower原型:function intpower(base:float;const exponent:Integer):float功能:返回base的exponent次方ldexp原型:function ldexp(x:float;const p:Integer):float功能:返回2的p次方乘以xlog10原型:function log10(x:float):float功能:返回x的常用对数log2原型:function log2(x:float):float功能:返回x以2为底的对数logn原型:function logn(n:float;x:float):float功能:返回x以n为底的对数Max原型:function Max(a:Integer;b:Integer):Integerfunction Max(a:Int64;b:Int64):Int64function Max(a:Extended;b:Extended):Extended 功能:返回a与b中较大的一个Min原型:function Min(a:Integer;b:Integer):Integerfunction Min(a:Int64;b:Int64):Int64function Min(a:Extended;b:Extended):Extended 功能:返回a与b中较小的一个arcsin原型:function arcsin(x:float):float功能:返回x的反正弦值,返回的是弧度指单位arccos原型:function arccos(x:float):float功能:返回x的反余弦值,返回的是弧度指单位tan原型:function tan(x:float):float功能:返回x的正切值,x以弧度为单位cotan原型:function cotan(x:float):float功能:返回x的余切值,x以弧度为单位arcsinh原型:function arcsinh(x:float):float功能:返回双曲线的反正弦arccosh原型:function arccosh(x:float):float功能:返回双曲线的反余弦arctanh原型:function arctanh(x:float):float功能:返回双曲线的反正切sinh原型:function sinh(x:float):float功能:返回双曲线的正弦cosh原型:function sinh(x:float):float功能:返回双曲线的正弦tanh原型:function sinh(x:float):float功能:返回双曲线的正切cycletorad原型:function cycletorad(cycle:float):float功能:返回圆的份数转换成弧度之后的值degtorad原型:function degtorad(deg:float):float功能:返回角度转换成弧度之后的值radtocycle原型:function radtocycle(rad:float):float功能:返回弧度转换成圆的份数之后的值radtodeg原型:function radtodeg(rad:float):float功能:返回弧度转换成角度之后的值MaxV alue原型:function maxvalue(const data:Array[] of float):floatfunction maxvalue(const data:Array[] of Integer):Integerfunction maxvalue(const data:PFloat;const N:Integer):floatfunction maxvalue(const data:PInteger;const N:Integer):Integer功能:返回数组中的最大值MinV alue原型:function minvalue(const data:Array[] of float):floatfunction minvalue(const data:Array[] of Integer):Integerfunction minvalue(const data:PFloat;const N:Integer):floatfunction MinV alue(const Data:PInteger;const N:Integer):Integer功能:返回数组中的最小值sum原型:function sum(const data:Array[] of float):floatfunction sum(const data:PFloat;const N:LongInt):float功能:求数组中所有数之和sumsandsquares原型:procedure sumsandsquares(const data:Array[] of float;var sum:float;var sumofsquares:float)procedure sumsandsquares(const data:PFloat;const N:Integer;var sum:float;var sumofsquares:float)功能:将数组中的数求和放入num中,求平方和放入sumofsquares中**原型:function operator **(float,float):float(bas:float;expo:float):floatfunction operator **(Int64,Int64):Int64(bas:Int64;expo:Int64):Int64功能:同等于Power,这是乘方的操作符具体例子可参看oi压缩包(二)Pascal过程与函数调用Abs语法Function Abs (r:Real):Real;Function Abs (r:Integer):Integer;Abs返回参数的绝对值。
最大子序列和设ans[i]表示前i个元素的最大和,a[i]表示元素数字则ans[i]:=max{ans[i-1]+a[i],a[i]}For i:=1 to n doAns[i]:=max(ans[i-1]+a[i],a[i]);Writeln(max{ans[n]});最大子矩阵对于一个矩阵而言,如果我们将连续k行的元素纵向相加,并对相加后所得的数列求连续最大和,则此连续最大和就是一个行数为k 的最优子矩阵在一序列中,sum[i]表示前i个元素的和sum[i]:=sum[i-1]+a[i]; 从i至j的元素和为sum[j]-sum[i]则对于一矩阵(n*m)Sum[i][j]表示第j列前i个元素的和求sum[i][j]For i:=1 to n doFor j:=1 to m doSum[i][j]:=sum[i-1][j]+a[i][j];从sum[i][j]中读取元素for i:=n downto 1 dofor j:=i-1 downto 0 dofor k:=1 to m dotemp[k]:=sum[i,k]-sum[j,k];不同的行组合数据处理方法第一行sum[1,j]第二行sum[2,j]-sum[1,j]第三行sum[3,j]-sum[2,j] 第一、二行sum[2,j]第二、三行sum[3,j]-sum[1,j] 第一、二、三行sum[3,j]则temp[k]表示每一小行每一小列的和(能全部记录)For i:=n downto 1 do //每一部分行[1,n]更新bestBeginFor j:=i-1 downto 0 doF or k:=1 to m doTemp[k]:=sum[i][k]-sum[j][k];End;只需从temp[k]中求出最大子序列和最终best即为所求a,sum:array[0..1000,0..1000] of longint;n,m:longint;procedure init;var i,j,k:longint;beginassign(input,'in.in');reset(input);readln(n,m);for i:=1 to n dofor j:=1 to m doread(a[i][j]);for i:=1 to n dofor j:=1 to m dosum[i][j]:=sum[i-1][j]+a[i][j]; //预处理记录第j列前i个元素和close(input);end;function max(a,b:longint):longint;beginif a>b then exit(a)else exit(b);end;procedure solve;var i,j,k,ans,tot:longint;temp,b:array[0..1000] of longint;begintot:=0;for i:=n downto 1 do //每一部分行for j:=i-1 downto 0 dobeginans:=-maxlongint;fillchar(b,sizeof(b),0);for k:=1 to m dotemp[k]:=sum[i][k]-sum[j][k];for k:=1 to m dobeginb[k]:=max(b[k-1]+temp[k],temp[k]);if ans<b[k] then ans:=b[k];end; //求最大子序列和if ans>tot then tot:=ans; //更新最大者end;writeln(tot);end;init; solve; end.["扫地"杯III day1]诡异的数学题From liouzhou_101背景Background“扫地”杯III NOIP2012模拟赛 day1 第一题描述Descriptionliouzhou_101从NOI归来后文化课像坨屎,于是决定去补做一些作业,结果翻开作业的第一题就傻眼了:设a、b、c为实数,且满足a+b+c=15,a^2+b^2+c^2=100,则a 的最大值和最小值的积为____。
NOIP知识点汇总加*号是选学,加粗为重点,重要值排序不分先后基础贪⼼、枚举、分治、⼆分、倍增、*构造、⾼精、模拟图论图最短路(dijkstra、spfa、floyd),差分约束最⼩⽣成树(kruskal、prim)并查集(扩展域)拓扑排序⼆分图染⾊,*⼆分图匹配tarjan找scc、桥、割点,缩点*分数规划树树上倍增(LCA)树的直径、树的重⼼dfs序*树链剖分数论gcd、lcm埃⽒筛法exgcd,求解同余⽅程、逆元快速幂*组合数学矩阵链表、队列(单调队列)、栈(单调栈)堆、st表、hash表线段树、树状数组字典树*分块动态规划背包DP、树形DP、记忆化搜索、递推区间DP、序列DP*DP优化(不涉及斜率优化、四边形不等式等等)搜索暴搜(dfs、bfs)搜索的剪枝启发式搜索(A*)迭代加深搜索、* IDA**随机化搜索其他算法STL的基本使⽤⽅法脑洞的正确使⽤⽅法*KMP*状态压缩冲省选的,先把整理的NOIP知识点学扎实,注意⼀定要学扎实加粗是重点,星号是选学学⽆⽌境,欢迎⼤家继续补充~图论⽹络流(dinic,SAP,ISAP选⼀个,费⽤流写EK就⾏。
*zkw费⽤流),⼆分图点分治,边分治,*动态点分治树链剖分,动态树,树分块虚树,*prufer编码*仙⼈掌算法带权并查集Splay(作为平衡树和维护区间),Treap,替罪⽺树线段树(权值线段树),树状数组,*线段树合并分块,块状链表,*双向链表凸包树套树主席树,可持久化trie,*其它可持久化数据结构莫队算法,*树上莫队,CDQ分治,整体⼆分⼆维线段树,*KDtree*舞蹈链,*⼆进制分组,*左偏树,*超哥线段树,*后缀平衡树,*fhqTreap 字符串相关及数据结构hash(⾃然溢出,双hash)kmp,AC⾃动机,trie后缀数组manacher,最⼩表⽰法*后缀⾃动机,*回⽂⾃动机,*后缀树数学线性筛,积性函数,容斥原理,莫⽐乌斯反演exgcd,费马⼩定理,Lucas定理,⾼中排列组合⾼斯消元,概率与期望相关中国剩余定理,BSGS,欧拉定理矩阵乘法单纯形法解线性规划FFT线性代数(⾏列式)*Simpson积分,⾼中求导与积分*群论*⽣成函数,多项式类算法博弈论相关,*密码学,阶,原根计算⼏何向量的点积/叉积,计算⼏何基础*⼆维计算⼏何相关,*三维计算⼏何相关*半平⾯交,*旋转卡壳,*三⾓剖分搜索A*,记忆化搜索,迭代深搜,双向⼴搜模拟退⽕,爬⼭算法,*随机增量法动态规划基础DP,树形DP,数位DP,状压DP,期望DP,基环树DP,*插头DP斜率优化,矩乘优化,单调队列优化,倍增优化,*四边形不等式优化trie图DP,*仙⼈掌DP其他算法构造,乱搞,随机化,三分法,打表,启发式合并Huffman树,2-sat,*朱刘算法说真的,计算⼏何要么全场不会,要么全场AK。
1时间复杂度
时间复杂度的分析方法
2排序算法
(1)平方排序算法(冒泡,插入,选择)
shell排序算法
(2)nlogn排序算法
快速排序(qsort,sort)
归并排序(求逆序对个数)
*
外部排序(堆排序)
3 数论
模运算
集合论
素数(Eratosthenes筛法)
进位制
欧几里德算法(辗转相除法)
扩展欧几里德算法(同余)ax + by = gcd(a,b)解线性同余方程ax ≡b(mod n)
*
中国剩余定理
高斯消元(线性代数)
4 数据结构
广度/ 宽度优先搜索及剪枝
表达式计算
Hash表
并查集
Tarjan算法(LCA最近公共祖先)
树状数组
*
线段树
5 动态规划(DP)
背包问题(背包九讲)
LIS(最长上升子序列)的二分优化
DP的队列优化(LCIS,单调队列)
区间的DP
树上的DP(记忆化搜索)
6 图论
单源最短路(dijkstra,floyd,spfa)
最小生成树(prim,kruskal)
拓扑排序
floyd求最小环
求图的强连通分量
判断图中是否有环
差分约束系统(就是求最长路,用spfa)
others:
指针(链表,搜索判重,邻接表,散列表,二叉树的表示,多叉树的表示)位运算
高精度的加减乘除开方(开方直接二分)
乘法转加法神器:log。
NOIP初赛知识点大全1. 编程基础知识1.1 语言基础•数据类型:包括整型、浮点型、字符型等;•变量和常量的使用;•表达式和运算符的使用。
1.2 控制流程•条件判断语句(如if语句)的使用;•循环语句(如for循环、while循环)的使用;•分支语句(如switch语句)的使用。
2. 数据结构与算法2.1 数组与字符串•数组的使用、创建和遍历;•字符串的各种操作,如拼接、截取、比较等;•字符串匹配算法,如KMP算法。
2.2 栈与队列•栈的基本操作,如入栈、出栈等;•队列的基本操作,如入队、出队等。
2.3 链表•单向链表的创建和使用;•双向链表的创建和使用;•循环链表的创建和使用。
2.4 树与图•二叉树的创建、遍历和搜索;•图的创建和遍历,如深度优先搜索(DFS)和广度优先搜索(BFS);•常见图算法,如最短路径算法和最小生成树算法。
2.5 排序与搜索•常见排序算法,如冒泡排序、快速排序、归并排序等;•二分查找算法。
3. 算法设计与优化3.1 贪心算法•定义和基本思想;•贪心算法的应用。
3.2 动态规划•定义和基本思想;•动态规划的应用。
3.3 回溯与递归•回溯算法的思想和应用;•递归算法的思想、应用和优化。
3.4 图论算法•最短路径算法,如Dijkstra算法和Floyd算法;•最小生成树算法,如Prim算法和Kruskal算法;•拓扑排序算法。
4. 数据存储与处理4.1 线性结构•数组的存储和处理;•栈和队列的存储和处理。
4.2 非线性结构•链表的存储和处理;•树的存储和处理;•图的存储和处理。
4.3 文件的读写与处理•文件的打开和关闭;•文件读取和写入操作。
4.4 数据的输入与输出•标准输入输出的使用;•文件输入输出的使用;•数据流的处理。
5. 编程技巧与调试5.1 编程技巧•数学计算技巧;•字符串处理技巧;•数据结构与算法的优化技巧。
5.2 调试技巧•代码调试的基本方法;•常见调试技巧。
NOIP算法总结与复习NOIP算法总结与复习(看了看李总的蓝⽪书,收获颇多,记下此⽂,以明志~~)(⼀)数论1、最⼤公约数,最⼩公倍数2、筛法球素数3、mod规律公式4、排列组合数,错排5、Catalan数6、康托展开7、负进制8、中位数的应⽤9、位运算(⼆)⾼精度算法1、朴素加法减法2、亿进制加法减法3、乘法4、除法5、亿进制读⼊处理6、综合运⽤(三)排序算法1、冒泡2、快排3、堆排4、归并(四)DP1、概念2、解题步骤3、背包类dp4、线性dp5、区间动态规划6、坐标型动态规划(规则类dp)7、资源分配型动态规划8、树型动态规划9、状态压缩的动态规划10、动态规划的⼀般优化⽅法(五)图论1、Floyd-Warshall2、Bellman-ford3、SPFA4、dijkstra5、prim6、kruskal7、欧拉回路8、哈密顿环9、flood fill(求图的强联通分量)10、最⼩环问题11、Topological sort12、次短路13、次⼩⽣成树(六)树1、堆2、⼆叉排序树3、最优⼆叉树(哈夫曼树)4、求树的后序遍历5、并查集及应⽤(七)分治1、⼆分查找2、⼆分逼近(注意精度问题)3、⼆分答案4、快排(见排序算法)5、归并排序(见排序算法)6、快速幂(⼋)贪⼼(九)搜索(⼗)其它1、离散化2、KMP3、字符串哈希4、常⽤字符串函数过程。
noip初赛知识点总结一、基础知识1.1 编程语言NOIP初赛主要使用C/C++和Pascal两种编程语言进行比赛。
参赛者需要熟练掌握这两种语言的基本语法和常用库函数,包括输入输出、变量声明、条件语句、循环语句、数组、字符串处理等。
1.2 数据结构参赛者需要了解各种常用的数据结构,包括数组、链表、栈、队列、堆、树、图等,以及它们的基本操作和应用场景。
此外,还需要掌握算法导论中的基本排序算法和查找算法,如插入排序、归并排序、快速排序、线性查找、二分查找等。
1.3 算法思想参赛者需要熟悉各种常见的算法思想,包括贪心算法、动态规划、分治算法、回溯算法、递归算法等,以及它们的应用场景和解题技巧。
此外,还需要了解图论中的基本算法,如最短路径算法、最小生成树算法、拓扑排序算法等。
1.4 数学知识NOIP初赛中经常涉及一些数学知识,参赛者需要了解基本的数论知识、组合数学知识、概率论知识、图论知识等,以便解决一些与数学相关的问题。
此外,还需要掌握常见的数学运算和函数求值方法。
二、经典题型2.1 模拟题模拟题一般是指模拟真实生活中的某种场景,要求参赛者根据题目描述进行逻辑推理和状态转移,最终得出正确的结果。
这类题型通常涉及数组、字符串、条件语句、循环语句等基本知识点,适合新手练手和熟悉编程语言。
2.2 数学题数学题一般是指涉及各种数学知识的问题,要求参赛者通过数学推导和运算得到最终结果。
这类题型通常涉及数论、组合数学、概率论、图论等知识点,适合对数学比较感兴趣的参赛者。
2.3 搜索题搜索题一般是指在给定的状态空间中,通过一定的搜索策略找到满足条件的解。
这类题型通常涉及深度优先搜索、广度优先搜索、状态压缩、剪枝等知识点,适合对算法思想比较感兴趣的参赛者。
2.4 动态规划题动态规划题一般是指通过维护一张状态转移表或者状态转移方程,找到最优解。
这类题型通常涉及最长上升子序列、最大子段和、背包问题、最优二叉搜索树等知识点,适合对算法思想比较感兴趣的参赛者。
团伙F r o m B e a r H s u 背景Background
经典题目
描述Description
1920年的芝加哥,出现了一群强盗。
如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。
而且有一点是肯定的,就是A的朋友的朋友是A的朋友;A的敌人的敌人也是A的朋友。
两个强盗是同一伙的当且仅当他们是朋友。
现在给你一些关于强盗们的信息,问你至多有多少个强盗团伙。
输入格式InputFormat
输入的第一行为N(2<=N<=1000),表示强盗的个数(从1编号到N)。
第二行M(1<=M<=5000),表示信息条数。
以下M行,每行可能是F p q或是E p q,分别表示p和q是朋友,或是敌人。
假设输入不会产生矛盾
输出格式OutputFormat
输出只有一行,表示最大可能的团伙数。
样例输入SampleInput
6
4
E 1 4
F 3 5
F 4 6
E 1 2
样例输出SampleOutput
3
每次读取,如果两人是朋友,则将两人直接合并。
如果两人(x , y)是敌人,将y加入x的每一个敌人中,将x加入y的每一个敌人中
var
n,m,tot:longint;
a:array[0..1000,0..1000] of longint;
father:array[0..1000] of longint;
function find(x:longint):longint;
begin
if father[x]=x then exit(x)
else father[x]:=find(father[x]);
exit(father[x]);
end;
function union(x,y:longint):longint;
begin
x:=find(x);
y:=find(y);
if x<>y then father[x]:=y;
end;
procedure solve;
var x,y,i,j:longint;
p:char;
begin
fillchar(a,sizeof(a),0);
readln(n);
readln(m);
for i:=1 to n do father[i]:=i; //初始化每一个都为独立集合{1}....{n} for i:=1 to m do
begin
readln(p,x,y);
if p='F' then union(x,y); //如果是朋友则合并
if p='E' then
begin
for j:=1 to (a[x][0]) do //将x的敌人并入所有x的敌人中(敌人的敌人是朋友)
union(y,a[x][j]);
for j:=1 to (a[y][0]) do //将y的敌人并入所有y的敌人中
union(x,a[y][j]);
inc(a[y][0]);a[y][a[y][0]]:=x; //y的敌人数加一,记录y的敌人inc(a[x][0]);a[x][a[x][0]]:=y; //x的敌人数加一,记录x的敌人end;
end;
tot:=0;
for i:=1 to n do if father[i]=i then tot:=tot+1;
writeln(tot);
end;
begin
solve;
end.
x,y是敌人将y与x的敌人合并(朋友)
初始{1} {2} {3} {4} {5} {6}
第一
次
{1} {2} {3} {4} {5} {6}
第二
次
{1} {2] 空{4} {5,3} {6}
第三
次
{1} {2} 空空{5,3} {6,4}
第四次{1} 空空空{5,3} {6,4,2
}
Ans=
3
1 0 0 0 1 1 第一次x,y敌人数加一
第四次将x,y的敌人分别并入
舞会From admin 描述Description
Victoria是一位颇有成就的艺术家,他因油画作品《我爱北京天安门》闻名于世界。
现在,他为了报答帮助他的同行们,准备开一个舞会。
Victoria准备邀请n个已经确定的人,可是问题来了:
这n个人每一个人都有一个小花名册,名册里面写着他所愿意交流的人的名字。
比如说在A的人名单里写了B,那么表示A愿意与B交流;但是B的名单里不见的有A,也就是说B不见的想与A交流。
但是如果A愿意与B交流,B愿意与C交流,那么A一定愿意与C 交流。
也就是说交流有传递性。
Victoria觉得需要将这n个人分为m组,要求每一组的任何一人都愿意与组内其他人交流。
并求出一种方案以确定m的最小值是多少。
注意:自己的名单里面不会有自己的名字。
输入格式InputFormat
第一行一个数n。
接下来n行,每i+1行表示编号为i的人的小花名册名单,名单以0结束。
1<=n<=200。
输出格式OutputFormat
一个数,m。
样例输入SampleInput
18
18 0
11 0
5 0
2 0
样例输出SampleOutput
16
来源Source
Vivian Snow
将其分为m组,使每一组任何一人都愿意与组内其他人交流,使m 最小可使用并查集。
将问题看作图,每一组数据连一条边,“那么表示A愿意与B交流;但是B的名单里不见的有A”,表明为无向图。
运用floyed算法(题目中n<=200),将所有有联系的边全部得出,如果两点有联系,则将其并入一集合,最终找到father[i]=i即为集合数,即最小m值。
(若对于i,对应数据为0,表示i不愿意与任何人交流,单独作为一集合)。
var
w:array[1..200,1..200] of boolean;
father:array[0 ..200] of longint;
n,ans:longint;
procedure init; //读取数据,若i愿意与别人交流,数据一行可能有多个var i,x,y:longint;
begin
readln(n);
for i:=1 to n do
begin
read(x);
if x<>0 then
begin
w[i,x]:=true;
while not eoln do
begin
read(y);
if y<>0 then
w[i,y]:=true;
end;
end;
end;
for i:=1 to n do
father[i]:=i; //初始化并查集
end;
procedure solve1;
var i,j,k:longint;
begin
for k:=1 to n do
for i:=1 to n do
for j:=1 to n do
w[i,j]:=w[i,j] or (w[i,k] and w[k,j]); //floyed建立每边联系end;
function find(x:longint):longint;
var i,j,root:longint;
begin
if father[x]<>x then father[x]:=find(father[x]); //找到元素根节点find:=father[x];
end;
procedure union(r1,r2:longint);
begin
father[r2]:=r1;
end; //合并集合procedure solve2;
var i,j,r1,r2:longint;
begin
for i:=1 to n do
for j:=1 to n do
begin
if w[i][j] then //边有联系
begin
r1:=find(i);
r2:=find(j);
if r1<>r2 then union(r1,r2); //若根节点不同,且两点有联系,则并入集合end;
end;
end;
procedure print;
var i:longint;
begin
for i:=1 to n do
if father[i]=i then inc(ans); //统计有几个集合
writeln(ans);
end;
begin
init;
solve1;
solve2;
print;
end.。