Noip2014普及组

来源:互联网 发布:ubuntu命令行支持中文 编辑:程序博客网 时间:2024/05/21 17:22

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<min) then                        begin                                min:=i/j-r;                                x:=i;                                y:=j;                        end;        writeln(x,' ',y);        close(input); close(output);end.


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<y then exit(x) else exit(y);end;begin        assign(input,'matrix.in'); reset(input);        assign(output,'matrix.out'); rewrite(output);        readln(n,i,j);        k:=min((min(min(i,j),n-i+1)),n-j+1);        i:=i-k+1; j:=j-k+1;        st:=4*n*(k-1)-4-4*k*(k-2);        inc(st);        dec(n,(k-1)*2);        if i=1 then inc(st,j-1)                else        if j=n then inc(st,n+i-2)                else        if i=n then inc(st,n*3-j-2)                else        inc(st,n*4-3-i);        writeln(st);        close(input); close(output);end.


T4:

题目大意:指在一个n*m的矩阵中选一个r*c的矩阵,当然这矩阵r行不一定相邻,c列也不一定相邻,但是选了第i行就必须选完,选第j列也必须选完。

例如:


5 5 2 39 3 3 3 99 4 8 7 41 7 4 6 66 8 5 6 97 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 (x<y) then exit(x) else exit(y); end;procedure work;begin        fillchar(sum,sizeof(sum),0);        fillchar(d,sizeof(d),0);        for i:=1 to m do                for j:=1 to r-1 do                        inc(d[i],abs(a[bz[j],i]-a[bz[j+1],i]));        for i:=1 to m-1 do                for j:=i+1 to m do                        for k:=1 to r do                                inc(sum[i,j],abs(a[bz[k],i]-a[bz[k],j]));        fillchar(f,sizeof(f),5);        for i:=1 to m do        begin                f[i,1]:=d[i];                for j:=2 to min(i,c) do                        for k:=1 to i-1 do                                f[i,j]:=min(f[i,j],f[k,j-1]+sum[k,i]+d[i]);                ans:=min(ans,f[i,c]);        end;end;procedure dg(k,tot:longint);begin        if k+(r-tot)>n 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.


0 0
原创粉丝点击