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

官网链接

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_pair

using 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值