破解石碑
【问题描述】
相传在上古时期留下了许多块神秘的石碑,石碑的正面按顺序刻上 N 个数字,并且每个数字的下方都有一个字号较小的数相对应。研究人员把上面的数字称为 A 列,下面的数字称为 B 列。
在查阅古书后人们得知,每块石碑其实都是一把锁。如果人们在石碑上按合适的方法对数字进行操作,就会获得巨大的能量。操作的规则如下:
若 Ai 和 Ai + 1 不互质,我们可以在原石碑中抹去第 i 和第 i + 1 个数(包括A 中和 B 中),然后将两个序列重新按顺序编号。
假如最终 B 列中被抹去的数的和达到可能的最大值,这把巨锁就解开了。
由于对石碑上数字的抹去是不可逆的,为了不浪费每块石碑,我们必须事先计算出每块石碑的操作方案并获得 B 列被删去的可能最大和。
【输入】
第 1 行一个整数 N;
第 2 行 N 个整数,依次表示 Ai;
第 3 行 N 个整数,依次表示 Bi。
【输出】
仅含一个整数,表示 B 列被删去的可能最大和。
【输入输出样例】
stele.in
6
9 8 6 5 6 3
11 19 12 17 18 15
stele.out
64
【数据范围】
对于 30%的数据,N ≤ 20;
对于 60%的数据,N ≤ 100;
对于 80%的数据,N ≤ 500
对于 100%的数据,N ≤ 800, 1 ≤ Ai, Bi ≤ 10^9
用g数组记录i,j两个点能否在一起(i,j之间的数字都被抹去),用f数组记录从i到j得到的最大答案。
program mys;
var t,h,i,j,k,m,n:longint;
g:array[0..900,0..900]of longint;
f:array[0..900,0..900]of int64;
a,b:array[0..1000]of longint;
sum:array[0..1000]of int64;
function gcd(a,b:longint):longint;
begin
if a mod b=0 then exit(b)
else exit(gcd(b,a mod b));
end;
begin
assign(input,'stele.in');reset(input);
assign(output,'stele.out');rewrite(output);
readln(n);
read(a[1]);
for i:=2 to n do
begin
read(a[i]);
if gcd(a[i],a[i-1])>1 then g[i-1,i]:=1;
end;
for i:=1 to n do
begin
read(b[i]);
sum[i]:=sum[i-1]+b[i];
end;
for i:=1 to n do
if g[i-1,i]=1 then
f[i-1,i]:=b[i-1]+b[i];
for i:=n downto 1 do
for j:=i+1 to n do
for k:=i+1 to j-1 do
if (i<>j)and(i<>k)and(j<>k) then
if ((g[i,k]=1) and (g[k+1,j]=1))or ((g[i+1,j-1]=1) and (gcd(a[i],a[j])>1)) then
begin
g[i,j]:=1;
f[i,j]:=sum[j]-sum[i-1];
end;
for i:=n downto 1 do
for j:=i+1 to n do
for k:=i to j do
if f[i,j]<f[i,k]+f[k+1,j] then f[i,j]:=f[i,k]+f[k+1,j];
writeln(f[1,n]);
close(input);
close(output);
end.
该博客探讨了古代石碑上的数字谜题,其中涉及动态规划算法解决如何通过特定操作最大化B列数字之和的问题。根据输入的石碑数字,通过计算找到最佳抹除策略,以达到最大的和。
863

被折叠的 条评论
为什么被折叠?



