牛客IOI周赛27补题-小H系列

一、小H的数列

1、题目描述

链接:https://ac.nowcoder.com/acm/problem/222053
来源:牛客网

在这里插入图片描述

2、题解思路

坐着不想写dp题了,就去看题解补补比赛题吧,这题比赛的时候没做出来,一直在求通项没整出来,后来看题解md,这通项求法不是很常规,数学不好只能含恨而终。求解过程自己又手写了一遍,比赛就该蒙一下,有了公式就套呗,高精度模板套一套,就过了
在这里插入图片描述

3、AC代码

#include<iostream>  
#include<cstring>  
#include<string>  
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string str1, str2;
    int a[100000], b[100000], c[1000000], len;   
    int i, j;
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    cin >> str1;
    str2 = str1;
    a[0] = str1.length();
    for (i = 1; i <= a[0]; i++)
        a[i] = str1[a[0] - i] - '0';
    b[0] = str2.length();
    for (i = 1; i <= b[0]; i++)
        b[i] = str2[b[0] - i] - '0';
    memset(c, 0, sizeof(c));
    for (i = 1; i <= a[0]; i++)    
        for (j = 1; j <= b[0]; j++)
        {
            c[i + j - 1] += a[i] * b[j];
            c[i + j] += c[i + j - 1] / 10;
            c[i + j - 1] %= 10;
        }
    len = a[0] + b[0] + 1;  
    while ((c[len] == 0) && (len > 1)) len--;   
    for (i = len; i >= 1; i--)
        cout << c[i];
    return 0;
}

二、小H的糖果

1、题目描述

链接:https://ac.nowcoder.com/acm/contest/11234/C
来源:牛客网

题目描述
小 H 生日的那一天,有人送给了小 H 1 颗糖果。小 H 觉得自己的糖果太少了,于是他学会了两种魔法:
<1>使糖果数 +1。
<2>让每一颗糖果分裂成 k 颗糖果,即让糖果总数乘以 k
小 H 想知道,他最少需要使用多少次魔法才能使糖果数刚好等于小 H 的幸运数字 n。
输入描述:
每个测试点包含多组测试数据。
第一行一个正整数 T,表示数据组数。
接下来共 T 行,每行两个正整数 k,n,含义见题目描述。
输出描述:
共 T 行,每行一个非负整数,表示使糖果数量刚好等于 n 的最少魔法使用次数。
链接:https://ac.nowcoder.com/acm/contest/11234/C
来源:牛客网

示例1
输入
复制
3
2 3
2 9
114514 1919810
输出
复制
2
4
87602
说明
样例解释:
对于第一组数据,可以连续使用2次魔法1,即1->2->3(数字表示使用魔法后的糖果数)
对于第二组数据,可以连续使用3次魔法2后再只用一次魔法1,即1->2->4->8->9。
在这里插入图片描述

2、题解思路

想着bfs一次过,写出来超时,过不了,看了题解思路(%%%)
<1>k==1,特判一下,因为只能使用n-1次加一
将题目转化为有一个初始值为 n 的变量 x,每次操作可以 除以 k(如果能整除) 或减去 1,求使 x变为 1的的最少步数。
<2>
若 n<k 则 加上 n-1(因为也即只能一直减 1),退出循环。
否则,ans 加上 n除以 k的余数加 1,再将 n设置为 n 除以 k 向下取整后的值,并继续循环。

3、AC代码

#include<iostream>  
#include<cstring>  
#include<string>  
#define int long long 
using namespace std;
int t, k, n, ans;
inline int read()
{
    int x = 0, f = 0;
    char ch = getchar();
    while (ch > '9' || ch < '0') { f |= (ch == '-'); ch = getchar(); }
    while (ch <= '9' && ch >= '0') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
    return f ? -x : x;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    t = read();
    while (t--) {
        k = read();
        n = read();
        ans = 0;
        if (k == 1) {
            printf("%lld\n", n - 1);
            continue;
        }
        while (n >= k) {
            ans += n % k + 1;
            n /= k;
        }
        ans += n - 1;
        printf("%lld\n", ans);
    }
    return 0;
}

三、旅游

1、题目描述

链接:https://ac.nowcoder.com/acm/contest/11234/D
来源:牛客网

题目描述
一放假,小 L 就开心规划好自己的假期安排。

她决定去 n 个旅游景点玩。而这些旅游景点之间达成了合作,某两个景点之间会有价格固定的直通大巴(中间不会在其他景点停车)。因此,小 L 决定旅游期间直接乘坐直通大巴在各个旅游景点间往返,并且她希望每次前往另一个景点时花费最小。
由于现在处于疫情期间,每个景点都应该按照规定进行消毒。因为小 L 非常怕感染,所以她决定,只乘坐起点和目的地都进行过至少一次消毒的大巴。

输入描述:
第一行是 n,m,s,q。代表这 n 个景点之间有 m 条线路(即直通大巴),小 L 现在正处在编号为 s 的景点,q 为信息数量。

我们默认 s 号景点已消过毒。

接下来 m 行,每行三个数 u,v,w。代表编号为 u 的景点与编号为 v 的景点之间存在票价为 w 的单向(从 u 到 v)直通大巴。(存在重边和自环,且有可能 u=v)

接下来 q 行是信息,每行两个数 op,x。

共有两种情况:

1 x,代表编号为 x 的景点进行了一次消毒。
2 x,代表小 L 要从当前景点 y 去到编号为 x 的景点。请注意,如果小 L 不能到达 x 号景点那么她的“当前位置”不变,即仍然在 y 号景点。否则“当前位置”为 x 号景点。

输出描述:
对于每个 op=2 的操作,如果 x 号景点没有进行过至少一次消毒,或者小 L 无法到达 x 号景点,请输出 -1 。否则,请输出从当前景点出发到 x 号景点的最小费用。

示例1
输入
复制
4 7 1 4
1 2 6335
3 3 6963
1 2 9962
2 1 2392
4 2 154
2 2 7422
1 3 9896
1 1
1 3
2 1
2 3
输出
复制
0
9896
说明
小L一开始就在 1 号景点,且已消毒。第一个 op=2 的情况小 L 的目的地为 1 号景点,故只需要花费 0 费用。

第二个 op=2 的情况,小 L 的“当前位置”为 1 号景点,目的地 3 号景点已消毒,最优的方案是通过 “1 3 9896” 这条路线,故输出 9896。

2、题解思路

弗洛伊德算法,再加个vis标记,我自己被坑在于emset函数,学到了怎么赋最大值(%%%牛客题解大佬)

3、AC代码

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int n, m, s, q;
int vis[1000], mp[400][400];
void floyd(int k){
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            if (mp[i][j] > mp[i][k] + mp[k][j]){
                mp[i][j] = mp[i][k] + mp[k][j];
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> s >> q;
    vis[s] = 1;
    memset(mp, 0x3f, sizeof mp);
    for (int i = 1; i <= n; i++) {
        mp[i][i] = 0;
    }
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        mp[u][v] = min(w, mp[u][v]);
    }
    floyd(s);
    while (q--) {
        int op,yy;
        cin >> op >> yy;
        if (op == 1) {
            if (!vis[yy]) {
                floyd(yy);
            }vis[yy] = 1;
            
        }else{
            if (mp[s][yy] == 0x3f3f3f3f || vis[yy]==0) {
                cout << "-1" << endl;
                continue;
            }else{
                cout << mp[s][yy] << endl;
                s = yy;
            }
        }
    }
	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值