海贼oj平台算法题目总结

本人博客
https://www.liyunxu.work/

#196.路飞爬楼梯

题目描述

这一节我们需要讨论的是一个递推的问题。在海贼理工学院有一个路飞君,他在爬楼梯的时候从来都是要么上 2 个台阶,要么上 3 个台阶。由于爬楼梯实在太无聊了,路飞君就开始尝试每天采用不同的方式上楼梯。如果路飞君回家需要爬 N 阶台阶,你能告诉路飞君,他爬楼梯回家有多少种不同的方式吗?

​请注意,路飞君“先爬 3 个台阶后爬 2 个台阶”和“先爬 2 个台阶后爬 3​ 个台阶”是两种不同的回家方式。

输入

测评机会反复运行你的程序。每次程序运行时,你的程序仅需输入一个符合描述的整数 N , 表示总共的台阶数 2 ≤ N ≤ 50 2≤N≤50 2N50

输出

输出为一行,输出一个整数,表示路飞君有多少种上楼梯的方式。最后结果保证在 int范围 内。

样例输入1

5

样例输出1

2

样例输入2

40

样例输出2

31572

实现

int func(int n) {
        if (n == 2 || n == 3) return 1;
        if (n == 1 || n == 0) return 0;
        return func(n - 2) + func(n - 3);
}

int main() {
        int n;
        scanf("%d", &n);
        printf("%d\n", func(n));
        return 0;
}

#184. 路飞吃桃

题目描述

路飞买了一堆桃子不知道个数,第一天吃了一半的桃子,还不过瘾,又多吃了一个。以后他每天吃剩下的桃子的一半还多一个,到 n 天只剩下一个桃子了。路飞想知道一开始买了多少桃子。

输入

输入一个整数 n ( 2 ≤ n ≤ 30 ) n(2≤n≤30) n(2n30)

输出

输出买的桃子的数量。

样例输入1

2

样例输出1

4

样例输入2

3

样例输出2

10

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

#include <stdio.h>

int func(int n) {
    int number = 0, temp = 1;
    if (n == 1) return 1;
    number = func(--n);
    number = (number + 1) * 2;
    return number;

}

int main() {
    int n;
    scanf("%d", &n);
    printf("%d\n", func(n));
    return 0;
}

#188.指定范围内的质数

题目描述

我们都知道,对于一个大于 1 的整数,如果除了 1 和它本身,它不再被其它正整数整除,那么我们说它是一个质数。

​ 请对于给定的一个大于 1 的正整数 N(你可以认为测评机给出的 N 均小于等于106 ),和一个大于 1 的正整数 M(你可以认为测评机给出的 M 均小于等于 106 ), N 一定大于 M,请按从小到大的顺序输出所有小于等于 N 且大于等于 M​ 的质数。

输入

测评机会反复运行你的程序。每次程序运行时,你的程序仅需输入两个正整数,分别为上述描述中的 N 和 M,两个正整数之间用一个空格分隔。

输出

请按从小到大的顺序输出所有小于等于 N 且大于等于 M 的质数,一个数单独占一行。

样例输入1

5 3

样例输出1

3
5

样例输入2

30 5

样例输出2

5
7
11
13
17
19
23
29

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

素数筛

#include <stdio.h>

#define MAX_N 1000000

int prime[MAX_N + 5];

void init_prime() {
    for (int i = 2; i <= MAX_N; i++) {
        if (prime[i]) continue;
        prime[++prime[0]] = i;
        for (int j = i, I = MAX_N / i; j <= I; j++) {
            prime[j * i] = 1;
        }
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    init_prime();
    for (int i = 1; i <= prime[0]; i++) {
        if (prime[i] < m) continue;
        if (prime[i] > n) break; 
        printf("%d\n", prime[i]);
    }
    return 0;
}

线性筛

#include <stdio.h>

#define MAX_N 1000000

int prime[MAX_N + 5];

void init_prime() {
    for (int i = 2; i <= MAX_N; i++) {
        if (!prime[i]) prime[++prime[0]] = i;
        for (int j = 1; j <= prime[0]; j++) {
            if (prime[j] * i > MAX_N) break;
            prime[prime[j] * i] = 1;
            if (!(i % prime[j])) break;
        }
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    init_prime();
    for (int i = 1; i <= prime[0] && prime[i] <= n; i++) {
        if (prime[i] < m) continue;
        printf("%d\n", prime[i]);
    }
    return 0;
}

#189. 实现折半查找

题目描述

我们刚刚学习了折半查找,但是还没有自己来实践一下,这一节,你就需要自己实现一个折半查找的程序啦。​ 给定 N 个整数和 K 个待查找的整数 M1,M2,…,Mk 。如果待查找的整数在给定的 N 个整数中,请输出待查找的整数是数组中第几个元素(从 1 开始计算,第一个元素计 1 而不是0 );

​如果待查找的整数不在给定的 N 个整数中,则输出 0 。

输入

测评机可能会反复运行程序,每次程序运行后,测评机输入包括三行。

​ 第一行输入两个整数N ( 1 ≤ N ≤ 106 ) ( 1≤N≤106 ) 1N106 K ( 1 ≤ K ≤ 106 ) K(1≤K≤106 ) K1K106,分别表示给定的整数总个数和待查找的数的个数;

​ 第二行从小到大输入 N 个整数 N u m b e r s i ( 1 ≤ N u m b e r s i ≤ 106 ,其中 1 ≤ i ≤ N ) Numbersi( 1≤Numbersi≤106 ,其中 1≤i≤N) Numbersi1Numbersi106,其中1iN,每两个整数之间用一个空格隔开;

​ 第三行输入 K 个整数 N u m b e r s j ( 1 ≤ N u m b e r s j ≤ 106 ,其中 1 ≤ j ≤ K ) Numbersj ( 1≤Numbersj≤106 ,其中 1≤j≤K) Numbersj1Numbersj106,其中1jK,每两个整数之间用一个空格隔开。

输出

输出为一行,包括 K 个部分,每个部分为题目描述中待查找的元素索引或 0 ,K 个部分之间用一个空格分隔。

​ 输出行尾不含多余空格。

样例输入1

3 1
1 4 6
4

样例输出1

2

样例输入2

5 2
1 4 6 7 8
5 1

样例输出2

0 1

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

#include <stdio.h>

#define MAX_N 1000000

int numbers[MAX_N + 5];
int search[MAX_N + 5];

int binary_search(int n, int x) {
    int head = 0, tail = n - 1, mid;
    while (head <= tail) {
        mid = (head + tail) >> 1;
        if (numbers[mid] == x) return mid + 1;
        if (numbers[mid] < x) head = mid + 1;
        else tail = mid - 1;
    }
    return 0;
}

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++) {
        scanf("%d", &numbers[i]);
    }
    for (int i = 0; i < k; i++) {
        scanf("%d", &search[i]);
    }
    for (int i = 0; i < k; i++) {
        i == 0 || printf(" ");
        printf("%d", binary_search(n ,search[i]));
    }
    printf("\n");
    return 0;
}

#190. 路飞的猜想

题目描述

有一天路飞突发奇想,他有一个猜想,任意一个大于 2 的偶数好像总能写成 2 个质数的和。路飞查了资料,发现这个猜想很早就被一个叫哥德巴赫的人提出来了,称为哥德巴赫猜想。目前还没有证明这个猜想的正确性。路飞告诉你一个整数 n ,让你用这个数去验证。

注意 1 不是质数。

输入

输入一个偶数 n ( 2 ≤ n ≤ 8000000 ) n(2≤n≤8000000) n(2n8000000)​ 。

输出

输出一个整数表示有多少对 ( x , y ) (x,y) (x,y) 满足 x + y = n ( x ≤ y ) x+y=n(x≤y) x+y=n(xy) 且x,y 均为质数。

样例输入1

10

样例输出1

2

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

#include <stdio.h>

#define MAX_N 8000000

int prime[MAX_N + 5];
int is_prime[MAX_N + 5];

void init_prime() {
    for (int i = 2; i <= MAX_N; i++) {
        if (!is_prime[i]) prime[++prime[0]] = i;
        for (int j = 1; j <= prime[0]; j++) {
            if (i * prime[j] > MAX_N) break;
            is_prime[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int main() {
    int n, cont = 0;
    init_prime();
    scanf("%d", &n);
    for (int i = 1; i <= prime[0] && prime[i] <= n / 2; i++) {
        if (!is_prime[n - prime[i]]) cont++;
    }
    printf("%d\n", cont);
    return 0;
}

#191. 素数距离

题目描述

路飞请你求出区间KaTeX parse error: Undefined control sequence: \[ at position 1: \̲[̲l,r\] 上距离最近的相邻的素数对和距离最远的相邻的素数对。 3,5 是相邻的素数,2,5 不是相邻的素数。距离定义为 2 个素数的差的绝对值。比如 5,7 距离为 2 。

输入

输入 2 个整数 l , r ( 1 ≤ l ≤ r ≤ 8000000 ) l,r(1≤l≤r≤8000000) l,r(1lr8000000)​ 。

输出

如果KaTeX parse error: Undefined control sequence: \b at position 7: a,b(a<\̲b̲)是距离最近的素数对, c , d ( c < d ) c,d(c<d) c,d(c<d) 是距离最远的素数对,按照如下格式输出 a,b are closest, c,d are most distant. 。如果最近或者最远有多对,输出 a 和 c 最小的。如果没有相邻是素数对,输出 There are no adjacent primes.

样例输入1

3 10

样例输出1

3,5 are closest, 3,5 are most distant.

样例输入2

14 17

样例输出2

There are no adjacent primes.

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

#include <stdio.h>
#include <limits.h>

#define MAX_N 8000000

int prime[MAX_N + 5];
int is_prime[MAX_N + 5];

void init_prime() {
    for (int i = 2; i <= MAX_N; i++) {
        if (!is_prime[i]) prime[++prime[0]] = i;
        for (int j = 1; j <= prime[0]; j++) {
            if (prime[j] * i > MAX_N) break;
            is_prime[prime[j] * i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int is_adjacent(int a, int b) {
    for (int i = a + 1; i < b; i++) {
        if (is_prime[i] == 0) return 0;
    }
    return 1;
}

int main() {
    int l, r, head = 0, tail = 0, min = INT_MAX, max = INT_MIN;
    int a, b, c, d;
    scanf("%d%d", &l, &r);
    init_prime();
    for (int i = l; i <= r; i++) {
        if (is_prime[i] == 1) continue;
        head = i;
        for (int j = i + 1; j <= r; j++) {
            if (is_prime[j] == 1) continue; 
            tail = j;
            if (tail - head < min) {
                min = tail - head;
                a = head;
                b = tail;
            }
            if (tail - head > max && is_adjacent(head, tail)) {
                max = tail - head;
                c = head;
                d = tail;
            }
            break;
        }
    }
    if (head == 0 || tail == 0) printf("There are no adjacent primes.\n");
    else printf("%d,%d are closest, %d,%d are most distant.\n", a, b, c, d);
    return 0;
}

#192. 方程求解

题目描述

有一个如下的方程需要你帮忙计算一下。
x e x = a xe^x=a xex=a
​ 其中, e 为自然底数,a 为常数。

​ 请你求出满足等式的 x 的值。

输入

输入一个整数 a ( 0 ≤ a ≤ 109 ) a(0≤a≤109) a(0a109)

输出

输出一个浮点数,表示方程的解,四舍五入到小数点后四位。

样例输入1

0

样例输出1

0.0000

样例输入2

1

样例输出2

0.5671

样例输入3

100

样例输出3

3.3856

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

#include <stdio.h>
#include <math.h>

double func(double a) {
    double head = 0.0, tail = a, mid;
    #define EPSL 1e-6
    while (tail - head > EPSL) {
        mid = (head + tail) / 2.0;
        if (mid * exp(mid) < a) head = mid;
        else tail = mid;
    }
    #undef EPSL
    return mid;
}

int main() {
    int a;
    scanf("%d", &a);
    printf("%.4lf\n", func(a));
    return 0;
}

#195. 报数游戏

题目描述

路飞在和他的朋友们一起玩一个游戏。由于路飞的机智,这个游戏由路飞担任裁判。

​ 首先,路飞会给他们一人一个编号,并且每个人的编号都不相同。接下来的每一回合,会给一个数,编号不超过它的最大编号的人要报出自己的编号。如果没有人的编号比路飞给出的数要小,那么编号最小的人要报出自己的编号。每个人可以重复报号。

​ 路飞会按照一个列表顺次报出每个回合的数,他的朋友们想知道每回合报出的编号应该是多少。你能帮帮他们吗?

输入

输入数据共 3 行。

​ 第一行有两个整数 n n n, m ( 1 ≤ n ≤ 105 , 1 ≤ m ≤ 105 ) m(1≤n≤105,1≤m≤105) m(1n105,1m105) ,分别表示参与游戏的路飞朋友的个数,和游戏的回合数。​ 第二行 n 个整数 a i ( 1 ≤ a i ≤ 108 ) ai(1≤ai≤108) ai(1ai108),表示朋友们每个人的编号。对于 0 ≤ i < j < n 0≤i<j<n 0i<j<n ,都有 a i < a j ai<aj ai<aj ,即他们的编号递增排列。​ 第三行 m 个整数 q i ( 1 ≤ q i ≤ 108 ) qi(1≤qi≤108) qi(1qi108) ,表示每回合路飞给的数字。

输出

输出共一行 m 个整数,表示每回合报出的编号,每两个整数之间一个空格,最后一个数后面没有空格。

样例输入1

5 5
1 5 10 15 20
3 6 12 18 24

样例输出1

1 5 10 15 20

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M

实现

#include <stdio.h>

#define MAX_N 100000

int number[MAX_N + 5];
int search[MAX_N + 5];

int binary_search(int n, int x) {
    int head = 0, tail = n - 1, mid;
    while (tail > head) {
        mid = (head + tail) >> 1;
        if (tail - head == 1) return tail;
        if (number[mid] > x) tail = mid;
        else head = mid;
    }
    return 0;
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) {
        scanf("%d", &number[i]);
    }
    for (int i = 0; i < m; i++) {
        scanf("%d", &search[i]);
        i == 0 || printf(" ");
        if (search[i] > number[n - 1]) printf("%d", number[n - 1]);
        else if (search[i] <= number[0]) printf("%d", number[0]); 
        else printf("%d", number[binary_search(n, search[i]) - 1]);
    }
    printf("\n");
    return 0;
}

#468. 最大公约数

题目描述

输入两个正整数m和n,求他们的最大公约数。

输入

一行两个正整数m和n,用一个空格隔开, 2 ≤ m 2≤m 2m n ≤ 10000 n≤10000 n10000

输出

一行一个正整数,表示m和n的最大公约数。

样例输入1

24 36

样例输出1

12

数据规模与限定

  • 时间限制:1 s
  • 内存限制:256 M
  • 100% 的数据保证 2 ≤ m 2≤m 2m n ≤ 10000 n≤10000 n10000

实现

#include <stdio.h>

int gcd(int m, int n) {
    return (n ? gcd(n, m % n) : m);
}

int main() {
    int m, n;
    scanf("%d%d", &m, &n);
    printf("%d\n", gcd(m, n));
}

#389. 暴躁的程序猿 (二分答案)

题目描述

某公司的程序猿每天都很暴躁,因为他们每个人都认为其他程序猿和自己风格不同,无法一同工作,当他们的工位的编号距离太近时,他们可能会发生语言甚至肢体冲突,为了尽量避免这种情况发生,现在公司打算重新安排工位,因为有些关系户的工位是固定的,现在只有一部分工位空了出来,现在有 N N N 个程序猿需要分配在 M M M 个工位中,第 i i i 个工位的编号为 X _ i X\_i X_i,工位编号各不相同,现在要求距离最近的两个程序猿之间的距离最大,求这个最大距离是多少。 X _ i X\_i X_i X _ j X\_j X_j 工位之间距离为 ∣ X _ i − X _ j ∣ |X\_i−X\_j| X_iX_j

输入

输入共 M+1 行。
​第一行两个整数 M,N。 ( 2 ≤ N ≤ M ≤ 100 , 000 ) (2≤N≤M≤100,000) 2NM100,000
​接下来 M 行,每行一个数,表示剩余的工位的编号。

输出

输出距离最近的两个程序猿之间的最大距离。

样例输入1

5 3
1
2
8
4
9

样例输出1

3

数据规模与限定

  • ​ 时间限制:1 s
  • 内存限制:256 M
  • 100% 的数据保证 2 ≤ N ≤ M ≤ 100 , 000 , 1 ≤ X i ≤ 1 , 000 , 000 , 000 2≤N≤M≤100,000,1≤Xi≤1,000,000,000 2NM100,0001Xi1,000,000,000

实现

#include<iostream>
#include <algorithm>

using namespace std;

int n, m, num[100005], mmin = 999999999;

int func(long long x) {
    int t = 1, last = num[0];
    for (int i = 1; i < n; i++) {
        if (num[i] - last >= x) {
            t += 1;
            last = num[i];
        }
    }
    return t;
}

int bs() {
    int l = mmin, r = num[n - 1] - num[0];
    while (l != r) {
        long long mid = (l + r + 1) >> 1;
        int s = func(mid);
        if (s >= m) l = mid;
        else r = mid - 1;
    }
    return l;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> num[i];
    }
    sort(num, num + n);
    for (int i = 1; i < n; i++) {
        mmin = min(mmin, num[i] - num[i - 1]);
    }
    cout << bs() << endl;
    return 0;
}

#78.大整数加法

题目描述

给定两个正整数m,n,计算两数之和

输入

两行数据,每行一个正整数。

输出

两数之和。

样例输入

1
2

样例输出

3

数据规模与限定

  • 时间限制:1 s
  • 内存限制:64 M
  • 对于10%的数据,1≤m,n≤109
  • 对于30%的数据,1≤m,n≤1019
  • 对于100%的数据,1 ≤m,n≤10100

实现和思路

我们以字符串的方式读入数据然后反着存入到数组中,然后对应位相加再处理进位,这里注意两个数相加最短的长度就是两个数字最长的长度。

#include <iostream>
#include <cstring>
using namespace std;

#define MAX_N 100

char str1[MAX_N + 5], str2[MAX_N + 5];
int num1[MAX_N + 5], num2[MAX_N + 5], ans[MAX_N + 5];

int convert(char *str, int *num) {
    int len = strlen(str);
    for (int i = len - 1; i >= 0; i--) {
        num[i] = str[len - i - 1] - '0';
    }
    return len;
}

void big_sum() {
    int n = convert(str1, num1);
    int m = convert(str2, num2);
    
    for (int i = 0; i < m; i++) {
        if (i >= n) num1[i] = 0;
        num1[i] += num2[i];
    }

    if (n < m) n = m;

    for (int i = 0; i < n; i++) {
        if (num1[i] < 10) continue;
        if (i == n - 1) num1[n] = 0, n += 1;
        num1[i + 1] += num1[i] / 10;
        num1[i] %= 10;
    }
    
    for (int i = n - 1; i >= 0; i--) {
        cout << num1[i];
    }
    cout << endl;
    return ;
}

int main() {
    cin >> str1 >> str2;
    big_sum(); 
    return 0;
}

#81.小明回家

题目描述

小明看完了电影,是时候回家了,可是这时他突然得知小米之家的小米9现货开卖了,这款手机小明已经想了一个多月,知道这个消息后的他十分兴奋,一定要在回家之前先去小米之家买手机(城市中有一个或多个小米之家),请计算小明从电影院到任意一个小米之家买手机后回家的最短距离(只能朝上下左右四个方向行走,除了障碍物外,其他地方都可以通过),数据保证可以买完手机后回家。

输入

第 1 行两个数 n 和 m 表示地图有 n 行 m 列 2≤n,m≤2000​ 第 2 行至第 n+1 行为地图 其中 S 表示电影院 T 表示家 P 表示小米之家​ . 为可以通过的点 # 为障碍物

输出

一个整数 表示小明从电影院去小米之家再回家的总距离

样例输入

5 5
.S…
###…
…T
.P##.
P…

样例输出

11

数据规模与限定

  • 时间限制:5 s
  • 内存限制:256 M
  • 100% 的数据保证 2≤n,m≤2000

实现和思路

这是一个最短路径走地图的问题,所以说我们采用广搜可以借助对队列进行广搜,还有这个题的每个点有三种状态、没手机走过、有手机走过、有没有手机都走过、还有家T也是一个可以走的点。

#include <iostream>
#include <queue>

using namespace std;

char mmap[2005][2005];
char mark[2005][2005];

int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};

struct node {
    int x, y, step, flag;
};

int main() {
    int n, m, sx, sy;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> mmap[i][j];
            if (mmap[i][j] == 'S') sx = i, sy = j;  
        }
    }
    
    queue<node> que;
    que.push((node){sx, sy, 0, 0});
    mark[sx][sy] = ;
    while (!que.empty()) {
        node temp = que.front();
        que.pop();
        for (int i = 0; i < 4; i++) {
            int xx = temp.x + dir[i][0];
            int yy = temp.y + dir[i][1];
            if (mmap[xx][yy] == 'T' && temp.flag == 1) {
                cout << temp.step + 1 << endl;
                return 0;
            }
            /* 如果没有手机 并且没有手机走过 */
            if (temp.flag == 0 && (mark[xx][yy] & 1) == 1) continue;
            if (temp.flag == 1 && (mark[xx][yy] & 2) == 2) continue;
            if (mmap[xx][yy] == '.' || mmap[xx][yy] == 'T' || mmap[xx][yy] == 'S') {
                mark[xx][yy] |= temp.flag + 1; // 有手机来过是2, 没手机来过则是1
                que.push((node){xx, yy, temp.step + 1, temp.flag});
            }
            if (mmap[xx][yy] == 'P') {
                mark[xx][yy] = 3; //直接标记成有没有手机都来过
                que.push((node){xx, yy, temp.step + 1, 1});
            }
        }
    }

    return 0;
}

#82. 伐木

题目描述

又到了伐木的季节呢!亚布力林业局引进了一台新的伐木设备,这种设备能设定一个高度值(整数),并将所有树木大于此高度的部分锯下来。​ 例如,有四棵树的高度分别为 20M 17M 15M 10M,把设备的高度设定为 15M,那么设备运行过后树的高度变为 15M 15M 15M 10M(从第一棵树锯下 5M,从第二棵树锯下 2M,总共锯下 7M)。​ 现在林业局需要至少锯下长度为 M 米的木头,因为国家推行的环保政策,林业局不能锯下过多的木材。需要将伐木设备的高度设定为多少才能使得获得的木材至少为 M 米?换句话说,如果再将高度升高一米,将得不到 M 米的木材,如果将高度减少一米,将不能通过环保政策。

输入

第一行两个个整数 N 和 M,N 表示树木的数量,M 表示需要木材的长度。​ (1≤N≤1000000 , 1≤M≤2000000000)​ 第二行 N 个整数表示每棵树的高度(≤1000000000)。所有数据必有解。

输出

一个整数,表示伐木的最高高度。

样例输入

4 9
20 17 15 10

样例输出

14

样例说明

将高度设定为 15M 时 将锯下 7M 木材 长度不足​ 将高度设定为 14M 时 将锯下 10M 木材 能锯下所需的 9M 木材的最高高度​ 将高度设定为 13M 时 将锯下 13M 木材 不能通过环保政策

数据规模与限定

  • 时间限制:1 s
  • ​ 内存限制:256 M
  • ​ 100% 的数据保证 1≤N≤1000000 , 1≤M≤2000000000

实现和思路

这是一个二分答案题是前面一堆1后面一堆0我们找最后一个一的情况(111110000)

#include <iostream>
using namespace std;

#define MAX_N 1000000

int nums[MAX_N + 5], m, n, mmax;

long long func(int t) {
    long long temp = 0;
    for (int i = 0; i < n; i++) {
        if (nums[i] - t > 0) {
            temp += nums[i] - t;
        } 
    }
    return temp;
}

int binary_search() {
    int head = 0, tail = mmax - 1;
    long long mid;
    while (head != tail) {
        mid = (head + tail + 1) >> 1;
        long long t = func(mid);
        if (t >= m) head = mid;
        else tail = mid - 1;
    }
    return head;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
        mmax = max(mmax, nums[i]);
    }
    cout << binary_search() << endl;
    return 0;
}


#226. a^b问题

题目描述

求 a 的 b 次方对 p 取模的值。

输入

输入三个整数 a,b,p。(0≤a,b≤109,1≤p≤109)

输出

输出 a 的 b 次方对 p 取模的值。

样例输入

5 4 15

样例输出

10

数据规模与限定

  • 时间限制:1 s
  • 内存限制:256 M
  • 100% 的数据保证 0≤a,b≤109,1≤p≤109

实现和思路

这里采用快速幂的方法具体查看我的常用算法笔记

#include <iostream>
#include <ctime>

using namespace std;

long long quick_mul(long long a, long long b, long long p) {
    int ans = 0;
    while (b) {
        if (b & 1) {
            ans = (ans + a) % p;
        }
        a = (a + a) % p;
        b >>= 1;
    }
    return ans % p;
}

long long quick_power(long long a,long long b, long long p){
    long long ans = 1;
    while (b > 0) {
        if (b & 1) { //(b % 2 == 1) 判断奇数
            ans = quick_mul(ans, a, p);
        }
        b >>= 1;
        a = quick_mul(a, a, p);
    }    
    return ans % p;
}

int main() {
    long long  a, b, p;
    clock_t start, finish;
    cin >> a >> b >> p;
    start = clock();
    long long ans = quick_power(a, b, p);
    finish = clock();
    cout << ans << " time " << (double)(finish - start) / CLOCKS_PER_SEC << endl;

    return 0;
}


题目描述

输入

输出

样例输入

样例输出

数据规模与限定

实现和思路


  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

时莫如初

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

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

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

打赏作者

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

抵扣说明:

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

余额充值