当前位置: 代码迷 >> 综合 >> 第九届“图灵杯”NEUQ-ACM程序设计竞赛个人赛错题笔记
  详细解决方案

第九届“图灵杯”NEUQ-ACM程序设计竞赛个人赛错题笔记

热度:13   发布时间:2023-12-04 23:00:54.0

目录

  • 官网链接
  • F-第二大数
  • H-特征值
  • I-最大公约数

官网链接

F-第二大数

题目描述
牛神对于第一的宝座感到厌倦,他开始研究第二大的贡献。
现在给你一个N个数的排列P,包含(1,2,…,N),其中对于任给的一组(L,R)(1 ≤ L < R ≤ N) ,定义XL,R为序列元素从下标L到R中第二大的数。
现在请聪明的你算出∑L=1N?1R=L+1NXL,R的结果,AC者可凭运气获得牛神签名照一张。
输入描述:
第一行为牛神想要研究的数字N,其中2 ≤ N ≤ 104
第二行为N的一个排列。
输出描述:
输出包括一个整数,表示所求结果。

示例1
输入
3
2 3 1
输出
5

题解:
首先是理解题意:即理解要求的表达式的意思。即:计算从
1 ~ 2,1 ~ 3,…,1 ~ n;
2 ~ 3,2 ~ 4,…,2 ~ n;
…;
n-1 ~ n;
以上区间中的第二大的数值之间相加的结果。
又因为题目的数据范围为104,可以O(n2)出解。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int a[N];
int main()
{
    int n;//根据时间复杂度,可以做O(n方)的scanf("%d",&n);for(int i = 1;i <= n;i++){
    scanf("%d",&a[i]);}long long res = 0;for(int i = 1;i <= n;i++){
    int mx = a[i],mi = -2e9;for(int j = i + 1;j <= n;j++){
    if(a[j] > mx)   mi = mx,mx = a[j];else if(a[j] < mx && a[j] > mi)   mi = a[j];res += mi;}}    cout << res;
}

H-特征值

题目描述
最近捷宝学习了线性代数的知识,并成功在期末考试中获得了100分的好成绩。
其中计算矩阵的特征值这一题型给他留下深刻印象。
出于好奇心,他决定利用假期时间仔细钻研特征值这一概念。经过长达好多好多好多好多天的闭关研究,捷宝提出了整数的特征值这一概念。
可爱的捷宝定义,对于任意的正整数X,它的特征值的计算方式为:
在这里插入图片描述

注:? ?为向下取整,即不超过当前数字的最大整数(?3.2?=3,?2.9?=2,?7?=7
现在捷宝想要把概念进行推广,他需要你帮忙设计一个程序,能够对于任意读入的一个正整数,快速计算它的特征值.
输入描述:
输入共包括1行,输入捷宝想要研究的数字X
其中1 ≤ X < 10500000
输出描述:
输出共包括一行,输出所研究数字的特征值
链接:https://ac.nowcoder.com/acm/contest/27302/H
来源:牛客网

示例1
输入
1225
输出
1360
说明
1225+122+12+1=1360

示例2
输入
99999
输出
111105
说明
99999+9999+999+99+9=111105

示例3
输入
314159265358979323846264338327950288419716939937510
输出
349065850398865915384738153697722542688574377708317

备注:
提示:由于本题中读入数据的数据范围较大,所以可以考虑使用int类型的数组来存储X的每一位,以便于后续操作。
计算答案和输出答案也同理,可以使用数组来存储数字的每一位。

题解:
题意是让我们求出将一个数的每一个除以10之后的数相加的结果(算上原来的数),其结果较大,需用高精度思想。下面是这题的代码,其中的思想只可体会,不易言传。

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+10;
char s[N];
int a[N],t;
int main()
{
    scanf("%s",s + 1);int n = strlen(s + 1);reverse(s + 1,s + n + 1);for(int i = n;i;i--)    a[i] = a[i + 1] + (s[i] ^ 48);for(int i = 1;i <= n || a[i];i++){
    a[i + 1] += a[i] / 10;a[i] %= 10;t = i;}for(int i = t;i;i--)   printf("%d",a[i]);return 0;
}

I-最大公约数

题目描述
雯雯沉迷学习数学无法自拔,他在闭关修炼中遇到了难题,聪明的你能帮他解答吗?
现在给你一个N个数的序列P,定义X为这N个数的最大公因数,你可以进行无限次操作,每次操作选择一组(L,R)(1 ≤ L != R ≤ N,PL≥ 1),使得PL - 1且PR + 1,每次操作产生新的序列P。请问所有可能产生的P对应的X最多有多少个。AC者可凭RP获得雯雯签名照一张。
定义:A是序列P的一个公因数当且仅当序列P的每一个元素都能被A整除,且A≥1。
注意:本题规定任何正整数都是0的公因数。
输入描述:
第一行包含一个数 N,其中2 ≤ N ≤ 500。
第二行为长度为N的一个序列,其中序列元素P满足
1 ≤ P ≤ 106
输出描述:
输出包括一个整数,表示所有序列产生的最大公因数的个数。

示例1
输入
3
1 1 2
输出
3

说明
第一次操作,L=1,R=2,操作后P=0,2,2,此时P的最大公因数为2。

第二次操作,L=2,R=3,操作后P=0,1,3,此时P的最大公因数为1。

第三次操作,L=2,R=3,操作后P=0,0,4,此时P的最大公因数为4。

经过若干次操作后,序列P产生的最大公因数为1,2,4,共3个。

题解:
对任意x,若x为序列的因数,即有:
x | a[1],x | a[2],x | a[3],…x | a[n]
令sum = a[1] + a[2] + a[3] + … + a[n]
则:x | sum
即最多可能产生的序列的因数的数量即为sum的不同因数个数。直接对序列求和,计算和的不同因数的个数即可。
下述代码运用了试除法求约数的模板。

#include <bits/stdc++.h>#define pb push_back
#define fi first
#define se second
#define mp make_pairusing namespace std;typedef pair<int, int> PII;
typedef long long LL;template <typename T> bool chkMax(T &x, T y) {
     return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) {
     return (y < x) ? x = y, 1 : 0; }template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();while (s < '0' || s > '9') {
     if (s == '-') f = -1; s = getchar(); }while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();x *= f;
}int x;int main() {
    int n; cin >> n;while (n--) {
    int t; cin >> t;x += t;}int cnt = 0;for (int i = 1; i <= x / i; i++) {
    if (x % i == 0) {
    cnt++;if (x / i != i) cnt++;//约数成对出现,需要判重}}cout << cnt;return 0;
}
  相关解决方案