T2:
题目描述
在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有 1498 人,反对的有 902 人,那么赞同与反对的比例可以简单的记为
1498:902。
不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例的数值太大,难以一眼看出它们的关系。对于上面这个例子,如果把比例记为 5:3,虽然与真实结果有一定的误差,但依然能够较为准确地反映调查结果,同时也显得比较直观。
现给出支持人数 A,反对人数 B,以及一个上限 L,请你将 A 比 B 化简为 A’比 B’,要求在 A’和 B’均不大于 L 且 A’和 B’互质(两个整数的最大公约数是 1)的前ᨀ下, A’/B’ ≥ A/B且 A’/B’ - A/B 的值尽可能小。
输入
输入文件名为 ratio.in。
输入共一行,包含三个整数 A, B, L,每两个整数之间用一个空格隔开,分别表示支持人数、反对人数以及上限。
输出
输出文件名为 ratio.out。
输出共一行,包含两个整数 A’, B’,中间用一个空格隔开,表示化简后的比例。
样例输入
1498 902 10
样例输出
5 3
数据范围限制
【数据说明】
对于 100%的数据, 1 ≤ A ≤ 1,000,000, 1 ≤ B ≤ 1,000,000, 1 ≤ L ≤ 100,A/B ≤ L。
这道题就是一道大大的水题,当然我竟然一次没做对,就是因为没看清楚a'/b'一定要大于a/b,就这样我第一次只水了80分,所以下次做题一定要细心,把题目的每个要求及条件都在草稿纸上一一列出来方便检查和调试。
代码:
var
r,min:real;
a,b,l,i,j,x,y:longint;
function gcd(x,y:longint):longint;
var
z:longint;
begin
while x mod y<>0 do
begin
z:=x mod y;
x:=y;
y:=z;
end;
exit(y);
end;
begin
assign(input,'ratio.in'); reset(input);
assign(output,'ratio.out'); rewrite(output);
readln(a,b,l);
r:=a/b;
min:=maxLongint;
for i:=1 to l do
for j:=1 to l do
if (gcd(i,j)=1) and (i/j>=r) and (i/j-r
T3:
题目大意:这道题的题目意思是说在一个n*n的螺旋矩形中,求出第i行第j个是什么数。
样例输入:
4 2 3
样例输出:
14
表示4*4的一个螺旋矩阵的第2,3个数是14.
这道题关键是要想到把一个螺旋矩阵分“层”,也就是把矩阵变成一个“回”字,一层一层的分开,然后想到这点之后还有一点就是如何判断i,j点在哪一层?
其实我们只要多找几个数,多摸索一下规律,我们就发现其实判断i,j点在哪一层,只用求出min(i,j,n-i+1,n-j+1)的值就行了,这个最小值一定是当前i,j点所在的层。然后当我们知道第i,j在哪一层之后,接下来就非常好办了,先把外围的层去掉,然后可以选择模拟,也可以用公式,总之根本不难实现,代码:
ar
n,i,j,st,k,l:longint;
function min(x,y:longint):longint;
begin
if x
T4:
题目大意:指在一个n*m的矩阵中选一个r*c的矩阵,当然这矩阵r行不一定相邻,c列也不一定相邻,但是选了第i行就必须选完,选第j列也必须选完。
例如:
5 5 2 3 9 3 3 3 9 9 4 8 7 4 1 7 4 6 6 6 8 5 6 9 7 4 5 6 1然后选完的矩阵的每个相邻之数的差的和就是这个矩阵的分值,现在要求你求一个最小分值。
该矩阵中分值最小的 2 行 3 列的子矩阵由原矩阵的第 4 行、第 5 行与第 1 列、第 3 列、第 4 列交叉位置的元素组成,为
答案=6
这道题目的难点在于,双重Dfs会超时,优化又太难加,而多维Dp根本也不会做,所以我们可以考虑降维的方法,也就是先dfs再dp,这样就能大大减少编程复杂度!
我们dfs选完行之后,就可以拿列来dp了,当然反之亦然。我们如何dp呢?我们可以想到阶段划分的是以每一列来划分,但是单单这一个条件不够,因为题目中还有一个条件就是只能选c列,也就是还要的一个阶段就是当前到了第i列选了多少列?所以我们可以设f[i,j]表示前i列选j列的最小分值。这里需注意的一点是:前i列当中第i列是必须得选的,所以,这个状态也可以表示成在必选第i列的情况下,再在前i-1列选j列的最小分值。
然后我们想一想决策,f[i,j]肯定是有f[..,j-1]加上第i列得来的,而这个空缺的空就是我们的决策,这里可以表示前k列选j-1列,然后再选第i列当做第J列。我们可以得到如下的一个状态转移方程:
f[i,j]:=min{f[k,j-1]+sum[k,i]+d[i]},sum[i,j]表示第i和第j两列横向分值差,而d[i]表示第i列纵向分值差,加上第i列其实只要加上这两个数即可。
代码:
var
n,m,r,c,i,j,k,ans:longint;
a,sum,f:array[0..16,1..16] of longint;
bz,d:array[0..16] of longint;
function min(x,y:longint):longint; begin if (xn then exit;
if tot>r then
begin
work;
exit;
end;
bz[tot]:=k;
dg(k+1,tot+1);
dg(k+1,tot);
end;
begin
assign(input,'submatrix.in'); reset(input);
assign(output,'submatrix.out'); rewrite(output);
readln(n,m,r,c);
for i:=1 to n do
for j:=1 to m do
read(a[i,j]);
ans:=maxlongint;
dg(1,1);
writeln(ans);
close(input); close(output);
end.