HDOJ

文章目录

  • #1003 Max Sum
  • #1004 Let the Balloon Rise
  • #1005 Number Sequence
  • #1008 Elevator
  • #1012 u Calculate e
  • #1013 Digital Roots
  • #1015 Safecracker
  • #1017 A Mathematical Curiosity
  • #1018 Big Number
  • #1019 Least Common Multiple
  • #1021 Fibonacci Again
  • #1037 Keep on Truckin'
  • #1342 Lotto
  • #1049 Climbing Worm
  • #1089 A+B for Input-Output Practice (I)
  • #1090 A+B for Input-Output Practice (II)
  • #1091 A+B for Input-Output Practice (III)
  • #1092 A+B for Input-Output Practice (IV)
  • #1093 A+B for Input-Output Practice (V)
  • #1094 A+B for Input-Output Practice (VI)
  • #1095 A+B for Input-Output Practice (VII)
  • #1096 A+B for Input-Output Practice (VIII)
  • #1097 A hard puzzle
  • #1098 Ignatius's puzzle
  • #1099 Lottery

#1003 Max Sum

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
解析链接:https://my.oschina.net/itblog/blog/267860

算法一(穷竭算法)

#include 
#include 

const int MAX_N = 100000;
int seq[MAX_N], T, kase = 0, first = true;

int main() {
    void resolve();
    scanf("%d", &T);
    resolve();
    return 0;
}

void resolve() {
    while (T--) {
        memset(seq, 0, sizeof(seq));

        int N, max_sum = 0, s = 0, t = 0;
        scanf("%d", &N);
        for (int i = 0; i < N; ++i)
            scanf("%d", &seq[i]);
        for (int i = 0; i < N; ++i) {
            for (int j = i; j < N; ++j) {
                int sum = 0;
                for (int k = i; k <= j; ++k)
                    sum += seq[k];
                if (sum > max_sum) {
                    max_sum = sum;
                    s = i;
                    t = j;
                }
            }
        }
        if (first)
            first = false;
        else
            printf("\n");
        printf("Case %d:\n", ++kase);
        printf("%d %d %d\n", max_sum, s + 1, t + 1);
    }
}

此算法比较简单,但时间复杂度为   O ( n 3 ) \ O(n^3)  O(n3)。提交会显示超时。

算法二

for (int i = 0; i < N; ++i) {
    int sum = 0;
    for (int j = i; j < N; ++j) {
        sum += seq[j];
        if (sum > max_sum) {
            max_sum = sum;
            s = i;
            t = j;
        }
    }
}

显然,此算法时间复杂度为   O ( n 2 ) \ O(n^2)  O(n2)。但提交时仍然超时。

算法三

#include 
#include 

const int MAX_N = 100000;
int seq[MAX_N], T, kase = 0, first = true;

int main() {
    void resolve();
    scanf("%d", &T);
    resolve();
    return 0;
}

void resolve() {
    while (T--) {
        memset(seq, 0, sizeof(seq));

        int N, max_sum = 0, this_sum = 0, s = 0, t = 0;
        scanf("%d", &N);
        for (int i = 0; i < N; ++i)
            scanf("%d", &seq[i]);

        // 如果全为负数
        bool all_negative = true;
        for (int i = 0; i < N; ++i) {
            if (seq[i] >= 0) all_negative = false;
        }
        if (all_negative) {
            max_sum = seq[0];
            s = 0, t = 0;
            for (int i = 1; i < N; ++i) {
                if (seq[i] > max_sum) {
                    max_sum = seq[i];
                    s = i, t = i;
                }
            }
        } else
            // 不全为负数
            for (int i = 0, j = 0; j < N; ++j) {
                this_sum += seq[j];
                if (this_sum > max_sum) {
                    max_sum = this_sum;
                    s = i;
                    t = j;
                } else if (this_sum < 0) {
                    this_sum = 0;
                    i = j + 1;
                }
            }
        if (first)
            first = false;
        else
            printf("\n");
        printf("Case %d:\n", ++kase);
        printf("%d %d %d\n", max_sum, s + 1, t + 1);
    }
}

#1004 Let the Balloon Rise

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1004

#include 
#include 
#include 
using namespace std;
const int MAX_N = 1005;
string colors[MAX_N];
typedef pair<string, int> BALLOON;
BALLOON B[MAX_N];

int main()
{
    void resolve();
    resolve();
    return 0;
}

void resolve()
{
    int N;

    while(cin>>N && N != 0)
    {
        int color_count = 0;
        for(int i = 0; i<N; i++)
        {
            cin>>colors[i];
            string color = colors[i];
            int j;
            for(j = 0; j<color_count; j++)
            {
                if(color == B[j].first)
                {
                    B[j].second++;
                    break;
                }
            }
            if(j>= color_count)
            {
                BALLOON b(color, 1);
                B[color_count++] = b;
            }
        }

        BALLOON popular = B[0];
        for(int i = 1; i<color_count; i++)
        {
            BALLOON b = B[i];
            if(b.second>popular.second)
            {
                popular = b;
            }
        }
        cout<<popular.first<<endl;
    }
}


#1005 Number Sequence

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005

#include 
#include 
const int MAX_N = 1000;
int F[MAX_N], A, B, n;

int main(){
	void resolve();
	resolve();
	return 0;
} 

void resolve(){
	int initF();
	while(scanf("%d %d %d", &A, &B, &n) !=EOF){
		// 终止条件
		if(A == 0 && B == 0 && n ==0 ) break;
		
		memset(F, -1 , sizeof(F));
		int cycle = initF();
		int res = F[n % cycle];
		printf("%d\n", res);
	}
}

// 返回循环周期
int initF(){
	F[1] = 1,F[2] = 1;
	int i, cycle;
	for(i = 3;i<MAX_N;i++){
		F[i] = ((A *F[i-1] + B*F[i-2]) % 7);
		if(F[i] == 1 && F[i-1] == 1){
			/* ① */
			break;
		}
	}
	cycle = i-2; /* ② */
	F[0] = F[cycle];
	return cycle;
}

上面这段代码比较神秘的地方在于,如果把②处的这一行移到①处,逻辑上没有任何问题,本地也能跑通,但提交的时候会报“除0”错误。有时候不得不说,编程是一种玄学。

#1008 Elevator

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1008

#include
const int MAX_N = 100;
int a[MAX_N];
int N;
int main()
{
    void resolve();
    resolve();
    return 0;
}

void resolve()
{
    while(scanf("%d", &N) == 1 && N !=0)
    {
        int t = 0, current = 0;
        for(int i = 0; i< N; i++)
        {
            scanf("%d", &a[i]);
        }
        t = N * 5;
        for(int i = 0; i< N; i++)
        {
            int next = a[i];
            if(next > current)
            {
                t += ((next-current) * 6);
            }
            else if(next < current)
            {
                t += ((current-next) * 4);
            }
            current = next;
        }
        printf("%d\n", t);
    }
}

这道题有一点没有讲明白的是,如果连续多次是同一楼层,那么每一楼层是不是仍然要加5秒。但实际在提交的时候,如果你不加,是不通过的。

#1012 u Calculate e

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1012

#include 

int main(){
    void resolve();
    resolve();
    return 0;
}

void resolve(){
    int fac(int);
    int n = 9;
    printf("n e\n- -----------\n0 1\n1 2\n2 2.5\n");
    for(int i= 3;i<=9 ;i++){
        printf("%d ", i);
        double e = 0;
        for(int j = 0;j<=i;j++){
            e+=(1.0 / fac(j));
        }
        printf("%.9f\n", e);
    }
}

int fac(int n){
    if(n == 0) return 1;
    return n * fac(n-1);
}

这道题坑的地方在于只有前面三个不需要后面补0,而后面的全部都是小数点后9位。所以把前三个单独输出。

#1013 Digital Roots

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1013

#include 
#include 
const int MAX_N = 1000;
char n[MAX_N];
void resolve();
int main()
{
    resolve();
    return 0;
}

void resolve()
{
    int getRoot(int);

    while(scanf("%s", n)!=EOF)
    {
        int len = strlen(n);
        if(len == 1 && n[0]=='0')
            break;

        int sum = 0;
        for(int i = 0; i<len; i++)
        {
            sum+=n[i]-'0';
        }
        int root = getRoot(sum);
        printf("%d\n", root);
    }
}

int getRoot(int n)
{
    int sum = 0;
    while(n!=0)
    {
        sum+=n%10;
        n /= 10;
    }
    if(sum<10)
        return sum;
    else
        return getRoot(sum);
}

#1015 Safecracker

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1015

#include 
#include 
#include 

using namespace std;
const int MAX_N = 13;
long long target;
char letter[MAX_N];

int main() {
    void resolve();
    resolve();
    return 0;
}

bool compare(int a, int b) {
    return a > b;
}

void resolve() {
    while (scanf("%lld %s", &target, letter)) {
        // 终止条件
        if (target == 0 && strcmp(letter, "END") == 0)break;

        int len = strlen(letter);

        sort(letter, letter + len, compare);
        bool ok = false;

        for (int i = 0; i < len; ++i) {
            for (int j = 0; j < len; ++j) {
                if (j == i) continue;
                for (int k = 0; k < len; ++k) {
                    if (k == j || k == i) continue;
                    for (int l = 0; l < len; ++l) {
                        if (l == i || l == j || l == k) continue;
                        for (int m = 0; m < len; ++m) {
                            if (m == i || m == j || m == k || m == l) continue;

                            int v = letter[i] - 'A' + 1;
                            int w = letter[j] - 'A' + 1;
                            int x = letter[k] - 'A' + 1;
                            int y = letter[l] - 'A' + 1;
                            int z = letter[m] - 'A' + 1;
                            long long res = (long long) (v - w * w + x * x * x - y * y * y * y + z * z * z * z * z);
                            if (target == res) {
                                printf("%c%c%c%c%c\n", letter[i], letter[j], letter[k], letter[l], letter[m]);
                                ok = true;
                                break;
                            }
                        }
                        if (ok) break;
                    }
                    if (ok) true;
                }
                if (ok) true;
            }
            if (ok) true;
        }
        if (!ok) printf("no solution\n");
    }
}

首先要降序排序。注意,这里不能使用pow函数求次方,会出现精度问题。还有,这道题没有说明白一点,就是各个字母不能重复出现。

#1017 A Mathematical Curiosity

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1017

#include 
#include 

int N;

void resolve();

int main() {
    scanf("%d", &N);
    resolve();
    return 0;
}

void resolve() {
    bool first = true;
    while (N--) {
        int n, m;
        int kase = 0;
        if (first)
            first = false;
        else
            printf("\n");
        while (scanf("%d%d", &n, &m) == 2) {
            if (!n && !m)break;
            int count = 0;
            for (int a = 1; a < n; ++a) {
                for (int b = a + 1; b < n; ++b) {
                    int Z = a * a + b * b + m;
                    int M = a * b;
                    if (Z % M == 0)
                        count++;
                }
            }
            printf("Case %d: %d\n", ++kase, count);
        }
    }
}

#1018 Big Number

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1018
解析链接:https://blog.csdn.net/courtneygeng/article/details/9897149

#include 
#include 

void resolve();

int main() {
    resolve();
    return 0;
}

void resolve() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        int num;
        scanf("%d", &num);
        double sum = 0;
        for (int j = 1; j <= num; ++j) {
            sum += log10(j);
        }
        int res = (int) sum + 1;
        printf("%d\n", res);
    }
}

任意一个正整数a的位数等于 ⌊ l o g 10 a ⌋ + 1 \lfloor log_{10}a \rfloor + 1 log10a+1。任意阶乘 A = n ! = 1 ⋅ 2 ⋅ 3 ⋅ ⋯ ⋅ n A=n!=1 \cdot 2 \cdot 3 \cdot \cdots \cdot n A=n!=123n,其位数为 ⌊ l o g 10 1 + l o g 10 2 + l o g 10 3 + ⋯ + l o g 10 n ⌋ + 1 \lfloor log_{10}1 + log_{10}2 + log_{10}3 + \cdots + log_{10}n\rfloor + 1 log101+log102+log103++log10n+1

#1019 Least Common Multiple

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1019

#include 
#include 

using namespace std;

int N;
const int MAX_M = 10000;
int nums[MAX_M];

void resolve();

int gcd(int, int);

int lcm(int, int);

int main() {
    scanf("%d", &N);
    resolve();
    return 0;
}

void resolve() {
    while (N--) {
        int m;
        scanf("%d", &m);
        for (int i = 0; i < m; ++i)
            scanf("%d", &nums[i]);
        int a = nums[0];
        for (int j = 1; j < m; ++j) {
            int LCM = lcm(a, nums[j]);
            a = LCM;
        }
        cout << a << endl;
    }
}

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

int lcm(int a, int b) {
    if (a < b) {
        int tmp = a;
        a = b;
        b = tmp;
    }
    return a / gcd(a, b) * b;
}

#1021 Fibonacci Again

#include 
#include 

using namespace std;

void resolve();

int main() {
    resolve();
    return 0;
}

void resolve() {
    int n;
    while (scanf("%d", &n) != EOF) {
        if (n % 4 == 2)
            cout << "yes" << endl;
        else
            cout << "no" << endl;
    }
}

#1037 Keep on Truckin’

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1037

#include 

int set[3];

int main() {
    void resolve();
    for (int i = 0; i < 3; ++i) {
        scanf("%d", &set[i]);
    }
    resolve();
    return 0;
}

void resolve() {
    bool crash = false;
    for (int i = 0; i < 3; ++i) {
        if (set[i] <= 168) {
            crash = true;
            printf("CRASH %d\n", set[i]);
            break;
        }
    }
    if (!crash) printf("NO CRASH\n");
}

#1342 Lotto

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1342
解析链接:https://blog.csdn.net/pengwill97/article/details/54850852

#include 

const int MAX_N = 13;
int ans[6], S[MAX_N], k;

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    void dfs(int, int);
    bool first = true;
    while (scanf("%d", &k) && k != 0) {
        for (int i = 0; i < k; ++i) {
            scanf("%d", &S[i]);
        }
        if (first)first = false;
        else printf("\n");

        dfs(0, 0);
    }
}

void dfs(int i, int j) { // i表示ans数组的索引,j表示S数组的索引
    void print_ans();
    if (i >= 6) {
        print_ans();
        return;
    }
    if (j >= k) return;
    ans[i] = S[j];
    dfs(i + 1, j + 1);
    dfs(i, j + 1);
}

void print_ans() {
    printf("%d", ans[0]);
    for (int l = 1; l < 6; ++l) {
        printf(" %d", ans[l]);
    }
    printf("\n");
}

#1049 Climbing Worm

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1049

#include 

int n, u, d;

int main() {
    void resolve();

    resolve();
    return 0;
}

void resolve() {
    while (scanf("%d%d%d", &n, &u, &d)) {
        if (!n && !u && !d) break;
        int cur_height = 0, time = 0;
        bool climb = true;
        while (cur_height < n) {
            if (climb)
                cur_height += u;
            else
                cur_height -= d;
            climb = !climb;
            time++;
        }
        printf("%d\n", time);
    }
}

#1089 A+B for Input-Output Practice (I)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1089

#include 

int main() {
    void resolve();

    resolve();
}

void resolve() {
    int a, b;
    while (scanf("%d%d", &a, &b) != EOF) {
        printf("%d\n", a + b);
    }
}

#1090 A+B for Input-Output Practice (II)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1090

#include 

int main() {
    void resolve();

    resolve();
}

void resolve() {
    int a, b, n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d%d", &a, &b);
        printf("%d\n", a + b);
    }
}

#1091 A+B for Input-Output Practice (III)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1091

#include 

int main() {
    void resolve();

    resolve();
}

void resolve() {
    int a, b;
    while (scanf("%d%d", &a, &b) != EOF) {
        if (!a && !b) break;
        printf("%d\n", a + b);
    }
}

#1092 A+B for Input-Output Practice (IV)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1092

#include 

int main() {
    void resolve();

    resolve();
    return 0;
}

void resolve() {
    int n, sum, tmp;
    while (scanf("%d", &n)) {
        if (!n) break;
        sum = 0;
        for (int i = 0; i < n; ++i) {
            scanf("%d", &tmp);
            sum += tmp;
        }
        printf("%d\n", sum);
    }
}

#1093 A+B for Input-Output Practice (V)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1093

#include 

int N;

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    scanf("%d", &N);
    for (int i = 0; i < N; ++i) {
        int M, sum = 0, tmp;
        scanf("%d", &M);
        for (int j = 0; j < M; ++j) {
            scanf("%d", &tmp);
            sum += tmp;
        }
        printf("%d\n", sum);
    }
}

#1094 A+B for Input-Output Practice (VI)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1094

#include 

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    int N, sum, tmp;
    while (scanf("%d", &N) != EOF) {
        sum = 0;
        for (int i = 0; i < N; ++i) {
            scanf("%d", &tmp);
            sum += tmp;
        }
        printf("%d\n", sum);
    }
}

#1095 A+B for Input-Output Practice (VII)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1095

#include 

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    int a, b;
    while (scanf("%d%d", &a, &b) != EOF) {
        printf("%d\n\n", a + b);
    }
}

#1096 A+B for Input-Output Practice (VIII)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1096

#include 

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    int N, M, sum, tmp;
    bool first = true;
    scanf("%d", &N);
    for (int i = 0; i < N; ++i) {
        scanf("%d", &M);
        sum = 0;
        for (int j = 0; j < M; ++j) {
            scanf("%d", &tmp);
            sum += tmp;
        }
        if (first) {
            first = false;
        } else {
            printf("\n");
        }
        printf("%d\n", sum);
    }
}

#1097 A hard puzzle

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1097

#include 
#include 

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    long long a, b;
    int digit[10]; // 存放个位数的数组,最多不超过10个:0~9
    while (scanf("%lld%lld", &a, &b) != EOF) {
        int last = (int) a % 10; // a的个位数
        int res = 1;
        memset(digit, -1, sizeof(digit));
        int digit_len = 0; // digit数组实际的元素个数
        for (int i = 0; i < b; ++i) {
            res *= last;
            res %= 10;

            // 查找新的个位数在不在digit数组中
            bool exit = false;
            for (int j = 0; j < digit_len; ++j) {
                if (res == digit[j]) { // 如果某个数已经在digit中,说明已经产生了一个循环,则退出
                    exit = true;
                    break;
                }
            }
            if (!exit) digit[digit_len++] = res; // 某个数不在digit中,则加入digit中
            if (exit)break;
        }

        int pos = (int) (b % digit_len);
        if (pos == 0) pos = digit_len - 1;
        else pos -= 1;
        printf("%d\n", digit[pos]);
    }
}

#1098 Ignatius’s puzzle

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1098

#include 

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    int k;
    while (scanf("%d", &k) != EOF) {
        int a;
        for (a = 1; a < 10000; ++a) {
            if ((18 + k * a) % 65 == 0) {
                printf("%d\n", a);
                break;
            }
        }
        if (a >= 10000) {
            printf("no\n");
        }
    }
}

由于对于任何的x都成立,取x=1,得 18+ka 。即只要(18+ka)%65 == 0即可。详细的证明可参考:https://blog.csdn.net/u014355480/article/details/44248493。在这里,由题意可知k<10000,而a与k的身份相同,均为因式,可认为a<10000,故for循环的条件是a < 10000 。

#1099 Lottery

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1099

#include 

typedef long long LL;

LL gcd(LL, LL);

LL lcm(LL, LL);

int digits(LL);

int main() {
    void resolve();
    resolve();
    return 0;
}

void resolve() {
    int n;
    while (scanf("%d", &n) != EOF) {
        LL z = 1, m = 1, integer = 0; // z分子, m分母, integer表示带分数的整数部分
        LL g; // 求最大公约数的临时变量
        for (int i = 2; i <= n; ++i) {
            LL old_m = m;
            m = lcm(m, i); // 分母
            z = z * (m / old_m) + (m / i); // 分子
        }
        z *= n;
        g = gcd(m, z);
        z /= g;
        m /= g;
        if (z % m == 0) { // 能整除
            printf("%lld\n", z / m);
        } else { // 不能整除,带分数
            integer = z / m;
            z %= m;

            for (int i = 0; i < digits(integer); ++i)
                printf(" ");
            printf(" %lld\n", z);
            printf("%lld ", integer);
            for (int i = 0; i < digits(m); ++i)
                printf("-");
            printf("\n");
            for (int i = 0; i < digits(integer); ++i)
                printf(" ");
            printf(" %lld\n", m);
        }
    }
}

// 最大公约数
LL gcd(LL a, LL b) {
    if (a == 0) return b;
    return gcd(b % a, a);
}

// 最小公倍数
LL lcm(LL a, LL b) {
    return a * b / gcd(a, b);
}

// 求一个数字的位数
int digits(LL number) {
    int i = 0;
    while (number > 0) {
        number /= 10;
        i++;
    }
    return i;
}

问题转化为求 n ( 1 1 + 1 2 + 1 3 + ⋯ + 1 n − 1 + 1 n ) n(\frac{1}{1}+\frac{1}{2}+\frac{1}{3}+\cdots+\frac{1}{n-1}+\frac{1}{n}) n(11+21+31++n11+n1)
要注意,这里求最大公约数要用辗转相除法,直接使用遍历求最大公约数会超时。

你可能感兴趣的:(算法)