AtCoder Regular Contest 159(A,B)

A

题目大意:
给你一个n ∗ * n的矩阵,矩阵中只有0和1,然后给的k是复制2 k ^ k k 个所给的n*n矩阵,每行放k个n ∗ * n矩阵,一共放k行。算最短路(0为没路,1为边权为1的路)
思路:
n很小,k很大,复制2 k ^k k个肯定做不到,猜测只需要原矩阵直接计算最短路,然后查询所输入的点%n。用第一个样例复制一下验证一下猜测:
这是通过Floyd算过的最短路之后的距离矩阵,可见复制的四个3 ∗ * 3方块完全一样。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f

void solve()
{
    int n, k;
    cin >> n >> k;
    int a[n][n];
    memset(a, 0x3f, sizeof a);
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < n; j ++ ){
            int x;
            cin >> x;
            if(x) a[i][j] = x;
        }

    for(int k = 0; k < n; k ++ )
        for(int i = 0; i < n; i ++ )
            for(int j = 0; j < n; j ++ )
                a[i][j] = min(a[i][j], a[i][k] + a[k][j]);

    int q;
    cin >> q;
    while(q -- ){
        LL s, t;
        cin >> s >> t;
        s --, t --;
        int tmp = a[s % n][t % n];
        if(tmp == INF){
            cout << -1 << endl;
        }else{
            cout << tmp << endl;
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int t = 1;
    // cin >> t;
    while(t -- ) solve(); 
    system("pause");    
    return 0;
}

B

每进行一次题目所说的操作相当于a变成了g ∗ * (a/g - 1),b变成了g ∗ * (b/g - 1),且新的a和b的g会大于(之前g的倍数)等于旧的g。
如果a和b相等,减一次就够
如果a和b相差1,那么每次操作就只能减1,进行的操作数就是min(a,b)
直接将a和b除等于g,如果a和b不互质就一直除到互质。需要找到一个最小的t使得gcd(a-t,b-t)min,这个t就是将a和b变成a-t和b-t需要的操作数。设gcd(a-t,b-t)=k,a-t = k ∗ * ka, b-t = k ∗ * kb, 两式相减可得k能整除a和b的差值,那枚举k,求最小t

#include <bits/stdc++.h>
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
typedef long long LL;
#define int LL

int solve(int a, int b)
{
    if(a == b) return 1;
    if(!a || !b) return 0;
    int d = abs(a - b);
    if(d == 1) return min(a, b);

    int g = __gcd(a, b);
    a /= g;
    b /= g;
    if(g > 1) return solve(a, b);
    if(a > b) swap(a, b); //不交换也一样
    int t = a % d;
    for(int i = 2; i <= d / i; i ++ ){
        if(d % i == 0){
            t = min(t, a % i);
            t = min(t, a % (d / i));
        }
    }
    a -= t;
    b -= t;
    return solve(a, b) + t;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int t = 1;
    // cin >> t;
    int a, b;
    cin >> a >> b;
    while(t -- ) cout << solve(a, b) << endl; 
    system("pause");    
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜·肉多多·狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值