2019-ICPC-银川 部分题目题解

B. So Easy

题目:给出一个 n n n*n 的矩阵·,矩阵初始时由0组成。对任意一行/列进行任意次的加1操作。然后将新的矩阵的某个元素置为-1。输入n和进行置-1操作后的矩阵。推出-1那个位置原来的值是多少。(保证只有一个 -1)

方法一

  • 读入矩阵时记录 -1 的位置 a i a j (ai,aj) 并将其置为0。遍历每一行,找到这一行的最小值,并使这一行的每一个元素减去这个最小值。然后遍历每一列执行同样操作。最后得到 a r [ a i ] [ a j ] -ar[ai][aj] 即所求值。注意找最小值时,不把 a r [ a i ] [ a j ] ar[ai][aj] 纳入比较。
  • 代码:
#include<iostream>
#include<cstdio>
#include<cmath>
const int mx = 1000+10;
const int INF = 0x3f3f3f3f3f;
int ar[mx][mx];
using namespace std;
int main()
{
    int n, ai, aj;
    scanf("%d", &n);

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            scanf("%d", &ar[i][j]);
            if(ar[i][j] == -1)
            {
                ai = i;
                aj = j;
                ar[i][j] = 0;
            }
        }
    }
    int minn;
    for(int i=1; i<=n; i++)
    {
        minn = INF;
        for(int j=1; j<=n; j++)
        {
            if(i != ai || j != aj)
            {
                minn = min(minn, ar[i][j]);
            }
        }
        for(int j=1; j<=n; j++)
        {
            ar[i][j] -= minn;
        }
    }
    for(int j=1; j<=n; j++)
    {
        minn = INF;
        for(int i=1; i<=n; i++)
        {
            if(i!=ai||j!=aj)
                minn = min(minn,ar[i][j]);
        }
        for(int i=1; i<=n; i++)
        {
            ar[i][j] -= minn;
        }
    }
    printf("%d\n",-ar[ai][aj]);
    return 0;
}

方法二

  • 显然,矩阵中每一个位置的值等于它所在的行的加1操作次数加上它所在的列的加1操作次数。假设在一个含 a r [ a i ] [ a j ] = 1 ar[ai][aj]=-1 的田字格里,-1所在位置原来的值为 x 1 + y 1 x_1+y_1 ,其相邻的两边的值分别为 x 1 + y 2 x_1+y_2 x 2 + y 1 x_2+y_1 ,其对角线位置的值为 x 2 + y 2 x_2+y_2 。则可知( x 1 + y 2 x_1+y_2 )+( x 2 + y 1 x_2+y_1 )-( x 2 + y 2 x_2+y_2 ) = ( x 1 + y 1 x_1+y_1 )。即我们所需要的求的值。(因为考虑到边界和角的问题,将-1在田字格里的位置分情况谈论了)
0 1 2 3 ···
1 ··· ··· ··· ···
2 ··· x 1 + y 1 x_1+y_1 x 1 + y 2 x_1+y_2 ···
3 ··· x 2 + y 1 x_2+y_1 x 2 + y 2 x_2+y_2 ···
··· ··· ··· ··· ···
  • 代码:
#include<iostream>
#include<cstdio>
#include<cmath>
const int mx = 1000+10;
const int INF = 0x3f3f3f3f3f;
int ar[mx][mx];
using namespace std;
int main()
{
    int n, ai, aj, ans;
    scanf("%d", &n);

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            scanf("%d", &ar[i][j]);
            if(ar[i][j] == -1)
            {
                ai = i;
                aj = j;
            }
        }
    }
    if(ai + 1 <= n && aj + 1 <= n)
    {
        ans = ar[ai][aj+1] + ar[ai+1][aj] - ar[ai+1][aj+1];
    }
    else if(ai - 1 >= 1 && aj + 1 <= n)
    {
        ans = ar[ai-1][aj] + ar[ai][aj+1] - ar[ai-1][aj+1];
    }
    else if(ai - 1 >= 1 && aj -1 >= 1)
    {
        ans = ar[ai][aj-1] + ar[ai-1][aj] - ar[ai-1][aj-1];
    }
    else if(ai + 1 <= n && aj + 1 <= n)
    {
        ans = ar[ai][aj-1] + ar[ai+1][aj] - ar[ai+1][aj-1];
    }
    printf("%d\n",ans);
    return 0;
}

I. Base62

题目:输入 x , y , z x, y, z 。符号“0”——“9”代表0到9,“A”——“Z”代表10到35,“a”——“z”代表36到61。现在需要将以 x x 为基底的整数 z z 转换为以 y y 为基底的整数 z z

  • 用Python直接大数运算
  • 代码:
a = input().split(); #字符串组保存xyz
x = int(a[0]); y = int(a[1])
z = list(a[2]);
z.reverse(); #反转
sum = 0; b = 1;
for i in z:
    if i.isdigit():
        sum += int(i)*b
    elif i.islower():
        sum += ((ord(i)-ord('a'))+36)*b #ord函数返回ASCLL值
    elif i.isupper():
        sum += ((ord(i)-ord('A'))+10)*b
    b *= x #x的幂增长
if sum == 0:
    print(0)
else:
    ans = []
    while sum > 0:
        ans.append(sum%y)
        sum = sum//y #sum就等于sum//y的小数部分
    ans.reverse()
    for i in ans:
        if i < 10:
            print(i,end='')
        elif i < 36:
            print(chr(ord('A')+i-10),end='')
        else:
            print(chr(ord('a')+i-36),end='')


N. Fibonacci Sequence

直接输出的水题

发布了47 篇原创文章 · 获赞 4 · 访问量 1279

猜你喜欢

转载自blog.csdn.net/listenhhh/article/details/103952408
今日推荐