7月4日晚上考试

作物杂交

题目描述

作物杂交是作物栽培中重要的一步。已知有𝑁种作物 (编号 1 至𝑁 ),第 𝑖 种作物从播种到成熟的时间为 𝑇𝑖 。作物之间两两可以进行杂交,杂交时间取两种中时间较长的一方。如作物 A 种植时间为 5 天,作物 B 种植时间为 7 天,则 AB 杂交花费的时间为 7 天。作物杂交会产生固定的作物,新产生的作物仍然属于 𝑁 种作物中的一种。
初始时,拥有其中𝑀 种作物的种子 (数量无限,可以支持多次杂交)。同时可以进行多个杂交过程。求问对于给定的目标种子,最少需要多少天能够得到。
如存在 4 种作物 ABCD,各自的成熟时间为 5 天、7 天、3 天、8 天。初始拥有 AB 两种作物的种子,目标种子为 D,已知杂交情况为 A × B → C,A × C → D。则最短的杂交过程为:
第 1 天到第 7 天 (作物 B 的时间),A × B → C。
第 8 天到第 12 天 (作物 A 的时间),A × C → D。
花费 12 天得到作物 D 的种子。

输入描述

输入的第 1 行包含 4 个整数 𝑁,𝑀,𝐾,𝑇,𝑁 表示作物种类总数 (编号
1 至 𝑁),𝑀表示初始拥有的作物种子类型数量,𝐾 表示可以杂交的方案数,𝑇 表示目标种子的编号。
第 2 行包含𝑁 个整数,其中第𝑖个整数表示第 𝑖 种作物的种植时间
𝑇𝑖(1≤𝑇𝑖≤100)
第 3 行包含 𝑀 个整数,分别表示已拥有的种子类型 𝐾𝑗 (1≤𝐾𝑗≤𝑀),𝐾𝑗 两两不同。
第 4 至 𝐾 + 3 行,每行包含 3 个整数 𝐴,𝐵,𝐶,表示第 𝐴 类作物和第
𝐵 类作物杂交可以获得第 𝐶 类作物的种子。
其中,1≤𝑁≤2000,1≤𝐾≤105,1≤𝑇≤𝑁, 保证目标种子一定可以通过杂交得到。

输出描述

输出一个整数,表示得到目标种子的最短杂交时间。

输入输出样例

输入
6 2 4 6
5 3 4 6 4 9
1 2
1 2 3
1 3 4
2 3 5
4 5 6
输出
16

样例说明

第 1 天至第 5 天,将编号 1 与编号 2 的作物杂交,得到编号 3 的作物种子。
第 6 天至第 10 天,将编号 1 与编号 3 的作物杂交,得到编号 4 的物种子。
第 6 天至第 9 天,将编号 2 与编号 3 的作物杂交,得到编号 5 的作物种子。
第 11 天至第 16 天,将编号 4 与编号 5 的作物杂交,得到编号 6 的作物种子。
总共花费 16 天。

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
typedef pair<int, int> PII;
int w[N], f[N];
bool have[N];

vector<PII> fa[N];

int dfs(int t)
{
    for(int i = 0; i < fa[t].size(); i++)
    {
        int a = fa[t][i].first, b = fa[t][i].second;
        if(!have[a]) dfs(a);
        if(!have[b]) dfs(b);
        if(have[a] && have[b]) 
        {
            have[t] = true;
            f[t] = min(f[t], max(w[a], w[b]) + max(f[a], f[b]));
        }
    }
    return f[t];
}
int main()
{
    int n, m, k, t;
    cin >> n >> m >> k >> t;
    memset(f, 0x3f3f, sizeof f);
    for(int i = 1; i <= n; i++) cin >> w[i];
    for(int i = 1; i <= m; i++)
    {
        int temp;
        cin >> temp;
        have[temp] = true;
        f[temp] = 0;
    }
    for(int i = 1; i <= k; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        fa[c].push_back({a, b}); 
    }
    cout << dfs(t);
    return 0;
}

7月4日晚

2523: 我在大东软的学生名片
题目描述

希望在热身赛里的各位在正赛中都能取得优异的成绩~ 祝大家有个快乐的小学期~

输入

输出
Happy practice semester
样例输入 复制

样例输出 复制

Happy practice semester

#include<bits/stdc++.h>
using namespace std;
 
int main(){
    int i,j,k;
    printf("Happy practice semester\n");
    return 0;
} 
2524: 金铲铲之战 (弱化版)
题目描述

在一个遥远的王国里,金铲铲是至高无上的荣誉象征,只有最聪明的战士才能获得它。今天,王国将举办一场选拔赛,只有通过智慧和策略的考验,才能赢得金铲铲。需要输入参赛者的姓名strN(有且仅有zmx、hyf、lh、ctb、bb)和选择的答案strM(有且仅有jin、chan)

输入

共一行,为两个字符串strN和strM,用空格隔开

输出

如果strM为"jin" 则输出"wow You got a golden shovel shovel !" 如果strM为"chan"则需判断参赛者: 要是参赛者是"lh"则输出"mystery guest !" 否则输出"regrettably"

样例输入 复制

ctb jin

样例输出 复制

wow You got a golden shovel shovel !

题解

这道题纯sb,出的题目有问题,而且没有换行不给过,整的我无语

#include<bits/stdc++.h>
using namespace std;
 
string strN,strM;
 
int main(){
    int i,j,k;
    cin>>strN>>strM;
    if(strM=="jin")
        printf("wow You got a golden shovel shovel !\n");
    else{
        if(strN=="lh")printf("mystery guest !\n");
        else printf("regrettably\n");
    }
    return 0;
}
2525: 数组切割
题目描述

你有一个包含 n 个整数 a1,a2,a3,……的数组,保证 n 是偶数。
现在请你将这个数组分成 n/2 段,定义第 i 段的值 f(i) 为 i * (a_l + a_(l+1) + … + a_(r - 1) + a_r),l 为第 i 段左端点,r为第 i 段右端点。
换句话说,第 i 段的值 f(i) 为 (该段的元素和 * i)。 现在求 f(1) + f(2) + … + f(n/2) 的最大值是多少

输入

第一行包含一个整数 n (1 <= n <= 1e5) —— 数组的大小
第二行包含 n 个整数 a1,a2,…an (-1e9 <= ai <= 1e9) —— 数组的元素

输出

输出一个整数,代表 f(1) + f(2) + … + f(n/2) 的最大值

样例输入 复制

6
6 -8 4 9 11 -10

样例输出 复制

36

提示

最优方法为 [6, -8], [4], [9, 11, -10]

f(1) = 6 - 8 = -2

f(2) = 2 * (4) = 8

f(3) = 3 * (9 + 11 - 10) = 30

f(1) + f(2) + f(3) 最大值为 36

void solve() {
    int n;
    std::cin >> n;
 
    std::vector<int> a(n);
    i64 ans = 0;
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
        ans += a[i] * (i + 1);
    }
 
    i64 res = 0;
    std::vector<int> v;
    for (int i = n - 1; i > 0; i--) {
        i64 now = res + a[i];
        res += a[i];
        v.push_back(now);
    }
    sort(v.begin(), v.end());
 
 
    for (int i = 0; i < n / 2; i++) {
        ans -= *v.begin();
        v.erase(v.begin());
    }
//2525
2526: 平方数
题目描述

给定一个长度为N的非负整数序列 A=(A1,…,AN) 。求出满足以下两个条件的整数对 (i,j)的数量:
1≤ i < j ≤ N
Ai与Aj乘积为平方数。
当非负整数 a 可以使用某个非负整数 b 表示为 a=b2 时,非负整数a称为平方数。

输入

第一行给定一个N表示非负整数序列A的长度
第二行N个数,表示A序列
2 <= N <= 1e5
0 <= Ai<= 1e5

输出

一个非负整数,表示最终答案

样例输入 复制

5
0 3 2 8 12

样例输出 复制

6

题解

这道题数据范围10^5实际上根本没有到!
基本上都是两层循环来解决这道题的
真正的算法如下:
对于所有的平方数,对于答案的贡献为0,所以可以直接删掉,然后我们根据剩下的来组合,得到最终的结果

#include<bits/stdc++.h>
using namespace std;
 
int n,a[100005],ans;
int main(){
    int i,j,k;
    cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++){
        for(j=i+1;j<=n;j++){
            int x=a[i]*a[j];
            int sq=sqrt(x);
            if(sq*sq==x)ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}
2527: 最少硬币数量组合
题目描述

给定三种不同面额的硬币,以及一个目标金额。
请设计一个算法,计算出用这些硬币组合成目标金额所需的最少硬币数量。
如果无法凑出目标金额,则返回 -1。

输入

第一行包含三个整数,分别表示三种硬币的面额 a, b, c。
第二行包含一个整数 n,表示目标金额。

输出

输出一个整数,表示凑出目标金额所需的最少硬币数量。
如果无法凑出目标金额,输出 -1。

样例输入 复制

1 5 10
18

样例输出 复制

5

提示

样例解释:使用1个10元硬币,1个5元硬币和3个1元硬币,总共需要1+1+3 = 5个硬币可以凑出18元。

  • 每种硬币的数量没有限制。
  • 保证输入的硬币面额互不相同。
  • 题目保证 0 < n < 1000, 0 < a, b, c < 100;
  • 尽量优化你的算法,以确保在给定的输入范围内高效运行。
题解

动态规划

2528: 字符串的前后缀
题目描述

给你两个由小写英文字母组成的字符串 S 和 T 。 S 和 T 的长度分别为 N 和 M 。当 T 的前 N 个字符与 S 相同时, S 就可以说是 T 的前缀。 当 T 的后 N 个字符与 S 相同时, S 就可以说是 T 的后缀。
如果 S 既是 T 的前缀,又是 T 的后缀,则打印 0 ; 如果 S 是 T 的前缀,但不是后缀,则打印 1 ; 如果 S 是 T 的后缀,但不是前缀,则打印 2 ; 如果 S 既不是 T 的前缀,也不是后缀,则打印 3 。

输入

第一行,包含两个整数 N 和 M(1≤N≤M≤100)
第二行,包含一个长度为 N 的字符串 S
第三行,包含一个长度为 M 的字符串 T

输出

根据题意输出

样例输入 复制

3 7
abc
abcdefg

样例输出 复制

1

题解

模拟

#include<bits/stdc++.h>
using namespace std;
int n,m;
char a[105],b[105];
int main(){
    int i,j,k;
    cin>>n>>m>>a+1>>b+1;
    int flag1=1,flag2=1;
    for(i=1;i<=n;i++){
        if(a[i]!=b[i])flag1=0;
    }
    for(j=1,i=m-n+1;i<=m;i++,j++){
        if(a[j]!=b[i])flag2=0;
    }
    if(flag1==1&&flag2==1)printf("0\n");
    if(flag1==1&&flag2==0)printf("1\n");
    if(flag1==0&&flag2==1)printf("2\n");
    if(flag1==0&&flag2==0)printf("3\n");
    return 0;
}
2529: 这是一道莫比乌斯反演问题
题目描述

有这样一个函数 f(x, y),x 和 y 为正整数,定义 f(x, y) 为(x + y)除以 10^8 的 余数
给你一个长度为 n 的正整数序列 a,让你求出下面表达式的值:
请添加图片描述
(注意:并没有让你计算总和除以 108 的余数)

输入

第一行,包含一个正整数 n(2≤n≤3×105)代表序列的长度
第二行,包含 n 个正整数的集合 a(1≤ai<108)

输出

输入一个数,表示表达式的结果

样例输入 复制

3
3 50000001 50000002

样例输出 复制

100000012

提示

样例解释:
f(a1 , a2) = 50000004
f(a1 , a3) = 50000005
f(a2, a3) = 3
因此,答案为 f(a1 , a2) + f(a1 , a3) + f(a2, a3) =100000012

题解

这道题难,需要考虑到数学思想
首先,我们不计算%10^8的问题,所有的数相加,应该每个都出现了n-1次,先相加
之后我们将数组排序,使用双指针
i指针在前为当前的数字,j为寻找到ai+aj相加大于10^8 的数子位置,由于数组 已经排序,所以之后的一定相加之和大于10^8,所以我们只需要减掉之后的数字即可

signed main()
{   
    cin >> n;
    int res = 0;
    for (int i = 1; i <= n; i ++ ) 
    {
        cin >> a[i];
        res += a[i] * (n - 1);
    }
    sort(a + 1, a + 1 + n);
     
    for (int i = 1; i <= n; i ++ )
    {
        int l = i + 1, r = n + 1;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (a[i] + a[mid] >= mod) r = mid;
            else l = mid + 1;
        } 
        res -= (n - l + 1) * mod;
    }
    cout << res << endl;
 
    return 0;
} //oj 2529
2530: 三角形里的正方形
题目描述

在一个二维平面上有三个点A(a, 0), B(0, b), C(0, 0), 求ACB三点构成的三角形内含有多少个面积为1的正方形,不足一整个正方形的,超过该正方形一半面积就算1个正方形。例如当 a=8,b=6时有24个正方形在这里插入图片描述

输入

两个非负整数a, b (1≤a≤106), (1≤b≤106)

输出

正方形个数

样例输入 复制

6 8

样例输出 复制

24

题解

这道题也是考察数学
首先从左向右搜索,计算从右边看的梯形中计算心昂对应的高度,如果大于0.5则属于,否则不属于
所有相对应的数字相加,得到最终的答案

2531: 小学题,考公题,你试试不?
题目描述

这是一道小学真题
5,3=28
7,6=55
4,5=21
a,b=?

输入

输入两个正整数a和b(0<a,b<=100)

输出

输出一个正整数c

样例输入 复制

5 3

样例输出 复制

28

题解

本题规律题目,不要把规律想的太复杂 c=a*a+b;

#include<bits/stdc++.h>
using namespace std;
 
int main(){
    int i,j,k;
    int a,b;
    cin>>a>>b;
    cout<<a*a+b<<endl; 
    return 0;
}
2532: 鼓励题!尽可能大的三位数
题目描述

输入一个三位数的正整数,将数字位置重新排列,组成一个尽可大的三位数。例如:输入213,重新排列可得到尽可能大的三位数是321。

输入

三位数的正整数。

输出

重排后尽可能大的三位数。

样例输入 复制

213

样例输出 复制

321

#include<bits/stdc++.h>
using namespace std;
 
int x,a[10],n=1;
int main(){
    int i,j,k;
    cin>>x;
    while(x){
        a[n++]=x%10;
        x/=10;
    }
    sort(a+1,a+1+3);
    for(i=3;i>=1;i--)
        printf("%d",a[i]);
    return 0;
}
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

徐苏洋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值