OI比赛的核心

今天和一个参加CSP复赛的家长交流了些事情,所以有感写了这个。如果觉得不对,欢迎拍砖。

问题来由

山东某家长,小朋友刚参加了 CSP-J 组复赛,第二题出现 TLE ,整个山东第二题 100 分只有 5 人。家长说孩子思路是正确的,能否申述。我和家长巴拉巴拉了一大堆,这些不是核心。我告诉家长,OI考试核心是算法的复杂度,而不是思路。任何题目都有好多种解法。OI考试的核心是数学,是数学,是数学。重要的事情说三遍。我用一个具体题目来分析问题。

题目

原题

HDU编号6124,http://acm.hdu.edu.cn/showproblem.php?pid=6124

描述

HazelFan 有两个正整数 a,b,他想计算 a mod b。 但现在他忘了 b 的值,只记得 a 的值,请告诉他不同的可能的求余结果的数量。

输入

第一行包含一个正整数 T(1 ≤ T ≤ 5),表示测试样例数。
对于每个测试样例: 一行,包含正整数 a(1 ≤ a ≤ 10^9)。

输出

对于每个测试用例: 单行包含一个非负整数,表示答案。

样例输入

2
1
3

样例输出

2
3

题目分析

就是求 a % b 值的可能性。

数学知识

数学的取模运算,而且是整数的取模运算。按照数学的定义,a % b 的余数 r ,r = a - k * b,其中 k = b / a 的商。

数据范围

正整数 T(1 ≤ T ≤ 5)。哪么原题你爱怎么写都能 100% 通过。

哪么我们用初学者最容易的方法,枚举遍历呗。

AC代码

#include <iostream>

using namespace std;

int main() {
    int t;
    cin>>t;

    while(t--) {
        int a,b=1,result = 1;
        cin>>a;
        for(;b<=a;b+=2) {
            result+=1;
        }
        cout<<result<<endl;
    }

    return 0;
}

复杂度分析

老铁,没问题,标准O(n^2)。

等一下,问题解决了?我们将题目做个修改,

升级版题目

题面不做任何修改,只是吧 T 的范围扩大到10^6,也就是 1e6 的数据集。欢迎参考以下的题目链接,http://47.110.135.197/problem.php?id=5121

输入

第一行包含一个正整数 T(1 ≤ T ≤ 10^6),表示测试样例数。
对于每个测试样例: 一行,包含正整数 a(1 ≤ a ≤ 10^9)。

题目分析

题目没有任何的变化,就是数据集放大,也就是 T 从 5 变成了 1e6 大小。

哪么意味着O(n^2)复杂度的解法,必然出现 TLE ,也就是说只能拿到部分分数。让OJ重新判决题目。果然结论如下图。

也就是意味必须对原有算法进行升级,才能拿到 AC 。

数学分析

本题的核心是数学。下面我们简单分类讨论一下,a mod b 情况:

1、如果 a ≤ b,则 a % b 有 (n + 1) / 2 种可能.;

2、如果 a ≥ b,则有 1 种可能.。

所以,总共有 (n + 1 ) / 2 + 1 种可能.。

哪么这样,利用数学分析,我们就将算法从 O(n^2) 变成 O(n)。其实 AC 代码不是核心,但是还是贴一下吧。

AC代码

#include <cstdio>
int main() {
    //freopen("1.in", "r", stdin);
    //freopen("1.out", "w", stdout);

    int t;
    scanf("%d", &t);
    
    int a;
    while (t--) {
        scanf("%d", &a);
        printf("%d\n", (a+1)/2+1);
    }

    //fclose(stdin);
    //fclose(stdout);
    
    return 0;
}

结论

OI考试核心是算法的复杂度,而不是思路。任何题目都有好多种解法。OI考试的核心是数学,是数学,是数学。重要的事情说三遍。

 

P.S.

道歉,工科男,文笔实在不咋地。大家不要介意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力的老周

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

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

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

打赏作者

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

抵扣说明:

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

余额充值