最大值"划分"对阵列的操作

时间:2014-12-25 10:38:46

标签: arrays algorithm prime-factoring number-theory

给定一组n正整数 a [1],a [2],...,a [n] m个良好的整数对< EM>(I'子> 1 ,J <子> 1 )中,(i 2 ,J <子> 2 ),..., (i m ,j m )其中1≤i k &lt; j k ≤n, n <= 100&amp;米&LT; = 100

编辑:每个好的对(ik,jk)满足以下条件:ik + jk是奇数,1≤ik

在一个操作中,您可以执行一系列操作: 取一个好的对(i k ,j k 和一些整数 v(v&gt; 1),它将两个数字 a [i k ] a [j k ] 除以这两个数字都由 v

组成

确定您可以在给定阵列上顺序执行的最大操作数。请注意,在描述的操作中可以多次使用一对。

我的方法:

我首先对每个数组进行素数分解。 给定一对好的(ik,jk),我们可以将它们的共同主要权力除以 A [ik] A [jk] 这两个数字即如果A[ik]=2^5 * 3^4A[jk]=2^3 * 3^7那么我们可以通过 2 3次并且除以 3 总数 4次。操作次数增加了共同主要权力的最小值,即 7

然后可以将操作总数作为所有良好配对的所有公共主要权力的总和。

但是,对于以下测试用例,我的代码失败

N=10 

M=9 

A[]=67108864 8 2 131072 268435456 256 16384 128 8 128 

Good Pairs :

4 9

5 10 

6 9 

9 10 

1 4 

3 8 

8 9 

1 2 

4 5

数组的每个元素都是2的不同幂。

2的功率而言,数组可以写成:

B[]= 26 3 1 17 28 8 14 7 3 7 //A[i] = 2^B[i]

选择每个好对并减去2的共同幂,我的答案将逐步推进为每个好对:

26 3 1 14 28 8 14 7 0 7 ans 3

26 3 1 14 21 8 14 7 0 0 ans 10

26 3 1 14 21 8 14 7 0 0 ans 10

26 3 1 14 21 8 14 7 0 0 ans 10

12 3 1 0 21 8 14 7 0 0 ans 24

12 3 0 0 21 8 14 6 0 0 ans 25

12 3 0 0 21 8 14 6 0 0 ans 25

9 0 0 0 21 8 14 6 0 0 ans 28

9 0 0 0 21 8 14 6 0 0 ans 28

处理每个好的对,我的代码给出答案为28

然而正确答案为31 。我需要帮助理解输出结果如何以及解决这个问题的方法。

PS:问题是Codeforces Div2 Round 284的问题E.

问题的链接: http://codeforces.com/contest/499/problem/E

2 个答案:

答案 0 :(得分:3)

通过在下图中找到最大matching可以解决此问题。对于每个数组值x,对于具有多重性的x的每个素因子,创建一个新的顶点。例如,如果x = 12,那么我们创建两个2个顶点和一个3个顶点。在对应于数组值的相同素数因子的顶点对之间形成边缘,形成良好的对。例如,在输入

A  B  C  # array indexes
8 12 18  # array
A B      # good pairs
B C,

图表有顶点

{A2a, A2b, A2c, B2a, B2b, B3, C2, C3a, C3b}

和边缘

{{A2a, B2a}, {A2a, B2b}, {A2b, B2a}, {A2b, B2b}, {A2c, B2a}, {A2c, B2b},
 {B2a, C2}, {B2b, C2},
 {B3, C3a}, {B3, C3b}}.

例如,取边{A2c, B2a}的意思是我们将标记为AB的数组条目除以2。操作顺序无关紧要。

现在,有一些算法可以找到最大的一般匹配,但它们很复杂,我很惊讶编程竞赛会以它为特色。事实证明,你已经遗漏了一个重要的约束条件,即好的数字对与奇数相加,这保证了图形将是二分的,因此适用于更简单的算法。根据实例的样子,从二分匹配切换到最大流量也是有利可图的,例如,2 A因子B和{{{1}}的五个顶点和六个边可以{1}}由两个顶点和一个具有三个容量单位的边代替。

答案 1 :(得分:0)

我强烈怀疑你需要做一些回溯。你是如何选择“好配对”的?如果你没有选择允许最长的替代链的“好对”序列会怎样?

您可以将初始数组视为“状态”:

// using JSON notation; in C use structs, in Java use classes...
initialState = {
   numbers: [67108864 8 2 131072 268435456 256 16384 128 8 128],
   pairs: [[9, 4], [5,10], [6,9], [9, 10]], // several missing
   depth: 0
}

然后,您可以尝试执行pairs.length替换中的一个以进入“子”状态(在此处将所选数字除以公共因子,并递增“深度”计算器);但是有可能执行这些替换中的一个取消了执行另一个不同替换的可能性:例如,我可以将9与4,或10,或6对...这意味着它通常是可能的达到一个不是最深的死胡同的“死胡同”。

使用http://en.wikipedia.org/wiki/Backtracking查找正确答案。如果它运行得太慢,你可以尝试一些修剪:避免多次访问同一个状态,跟踪所使用的唯一数字数组。