【c++】scanf、printf与cin、cout性能差异测试

测试题目:

一本通 2087:【22CSPJ普及组】解密(decode)

https://www.luogu.com.cn/problem/P8814

测试代码:

c++ 复制代码
// 注意:使用scanf和printf 在一本通上才能通过测试点7、8、9、10
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int main() {
//    freopen("./data/P8814_7.in", "r", stdin);
//    freopen("./data/P8814_7_2.out", "w", stdout);

    long long k, n, e, d;

    scanf("%lld", &k);
//    cin >> k;
    for (int i = 1; i <= k; i++) {
        //cin >> n >> e >> d;
        scanf("%lld%lld%lld", &n, &e, &d);
        long long p, q;

        // 推导过程
        // 条件
        // n = p*q;
        // e * d = p*q - p - q +2;
        // => p + q = n - e*d +2;
        // => p = n - e*d +2 - q;
        // => (n - e*d +2 -q)*q = n
        //  -q^2 + (n - e*d +2) * q - n = 0
        // q^2 + (e*d-n-2)*q + n = 0

        // int a=1;
        long long b = e * d - n - 2;
        long long c = n;

        long long delta = b * b - 4 * c;
        if (delta < 0) {
            //cout << "NO" << endl;
            printf("NO\n");
            continue;
        }

        long long sqrt_val = sqrt(delta);
        if (sqrt_val * sqrt_val != delta) { // 没有整数解
            //cout << "NO" << endl;
            printf("NO\n");
            continue;
        }

        if ((-b + sqrt_val) % 2 != 0) { // 没有整数解
            //cout << "NO" << endl;
            printf("NO\n");
            continue;
        }

        long long x1, x2;
        x1 = (-b + sqrt_val) / 2;
        x2 = (-b - sqrt_val) / 2;

        q = max(x1, x2); // 直接取正根

        p = n - e * d + 2 - q;
        if (p <= q && p > 0 && q > 0 && p * q == n) {
            //cout << p << " " << q << endl;
            printf("%lld %lld\n", p, q);
        } else {
            //cout << "NO" << endl;
            printf("NO\n");
        }
    }
    return 0;
}

测试结果

1.使用cin、cout,洛谷能全部ac,一本通7、8、9、10测试点运行超时;

2.使用scanf、printf,洛谷和一本通都能全部通过;

这个问题与C++标准输入输出的性能特性有关。在算法竞赛中,当遇到大规模数据时,输入输出效率会成为关键因素。以下是具体原因分析:

decode.cpp

复制代码
// ... existing code ...
#include <cstdio>  // 替换了原<iostream>头文件
// ... existing code ...

// 修改后的输入输出方式
scanf("%lld", &k);  // 替换cin >> k
printf("NO\n");     // 替换cout << "NO" << endl

主要原因有三点:

缓冲机制差异:scanf/printf使用C标准库的缓冲机制,而cin/cout默认与C标准库同步(可通过ios::sync_with_stdio(false)关闭),但即使关闭同步,字符串解析仍比C库慢

格式解析开销:cin需要动态解析数据类型,而scanf直接通过格式字符串指定类型,在数值解析场景效率更高

输出刷新策略:endl会强制刷新缓冲区,而\n不会。原代码中频繁使用cout << endl会产生额外刷新开销

对于测试数据量极大的情况(如1e5级别测试点),这些差异会被放大,最终导致使用cin/cout的版本超时。这是算法竞赛中常见的性能陷阱,也是OJ平台测试用例设计的考察点之一。

建议保持当前使用scanf/printf的实现,这是处理大规模数值型IO的标准优化方案。若坚持使用C++流,可尝试以下优化(但可能仍不如C函数快):

cpp

复制代码
ios::sync_with_stdio(false);
cin.tie(nullptr);

相关推荐
shylyly_13 分钟前
C++中的类型转换
开发语言·c++·匿名对象·隐式类型转换·拷贝优化
jinyishu_16 分钟前
哈希表原理与开放定址法C++实现
c++·哈希算法·散列表
cui_ruicheng1 小时前
Python数据分析(一):数据分析概述与环境搭建
开发语言·python·数据分析
心平气和量大福大1 小时前
C#-WPF-UserControl-生命周期(加载 退出)
开发语言·c#·wpf
小龙报1 小时前
【优选算法】1. 水果成蓝 2.找到字符串中所有字母的异位词
java·c语言·数据结构·数据库·c++·redis·算法
sunywz1 小时前
【c#】 Web Deploy一键发布,IIS部署全流程
开发语言·前端·c#
Brilliantwxx2 小时前
【Linux】 软件包管理器(yum)+ Vim使用
linux·运维·服务器·开发语言·编辑器·vim
雪的季节2 小时前
Python 线程同步与异步编程 全解析
java·开发语言
txzrxz2 小时前
数论:排列数、组合数、费马小定理、逆元、同余定理
c++·算法·数论·组合数·费马小定理·逆元·排列数
520拼好饭被践踏2 小时前
JAVA+Agent学习day22
java·开发语言·后端·学习