【CCF】201403-1 0ms

本文介绍了一个算法问题,如何在一个非零且各不不同的整数集合中找出所有相反数对的数量。通过使用数组来记录每个数的出现次数,该算法能够有效地解决此问题,适用于竞赛编程和算法练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
问题描述
  有 N 个非零且各不相同的整数。请你编一个程序求出它们中有多少对相反数(a 和 -a 为一对相反数)。
输入格式
  第一行包含一个正整数 N。(1 ≤ N ≤ 500)。
  第二行为 N 个用单个空格隔开的非零整数,每个数的绝对值不超过1000,保证这些整数各不相同。
输出格式
  只输出一个整数,即这 N 个数中包含多少对相反数。
样例输入
5
1 2 3 -1 -2
样例输出
2
*/

#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <string.h> //别漏
#include <string>   //别漏

using namespace std;

int a[501];

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

    int sum=0;

    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        if(x>=0) a[x]++;
        else
        {
            x=-x;
            a[x]++;    //不能写成a[-x]!
        }

        if(a[x]==2) sum++;
    }
    cout<<sum<<endl;
}

 

<think>我们正在解决Windows环境下打包Qt与CERN ROOT集成的应用程序时出现的动态链接库(DLL)缺失或调用错误问题,特别是关于`QueryWin32SubsystemHost`和`ext-ms-win32-subsystem-query-l1-1-0.dll`的错误。 ### 问题分析 该错误通常与Windows子系统API的调用有关。`ext-ms-win32-subsystem-query-l1-1-0.dll`是Windows 10中的一个API集(API Set)的虚拟DLL,它并不实际存在,而是由系统通过API Set机制映射到实际的系统DLL(如`kernel32.dll`或`kernelbase.dll`)。因此,这个错误可能是由于以下原因之一: 1. **应用程序直接或间接地引用了这个虚拟DLL**:可能是ROOT或Qt的某个模块使用了较新的Windows API,而打包环境或运行环境的系统版本不匹配。 2. **依赖扫描工具误报**:一些依赖扫描工具(如`windeployqt`或手动检查工具)可能错误地将这个虚拟DLL当作实际文件来查找,导致在打包时缺失。 3. **系统版本问题**:运行应用程序的Windows版本较旧(如Windows 7),而该API Set在旧系统中不存在。 ### 解决方案 #### 方法1:更新Windows SDK和运行时库 确保开发环境和目标系统都使用较新的Windows 10版本(至少是1607周年更新版或更高),因为API Set机制在此之后有较大变化。 #### 方法2:检查并更新依赖库 1. **更新ROOT和Qt版本**:确保使用的ROOT和Qt都是针对当前Windows SDK构建的。特别是ROOT,建议使用最新版本(如ROOT v6.26或更高),因为它们对Windows的支持更好。 2. **重新编译ROOT**:如果从源代码编译ROOT,确保使用最新的Windows SDK和Visual Studio(如VS2019或VS2022)。编译时,注意以下CMake选项: ```bash cmake -DCMAKE_INSTALL_PREFIX=your_install_path ^ -Dbuiltin_llvm=ON ^ -Druntime_cxxmodules=OFF ^ -Dbuiltin_xrootd=ON ^ -Dbuiltin_glew=ON ^ -Dbuiltin_afterimage=ON ^ -Dbuiltin_vdt=ON ^ -Dbuiltin_openssl=ON ^ -Dbuiltin_gl2ps=ON ^ -Dbuiltin_ftgl=ON ^ -Dbuiltin_sqlite=ON ^ -Dbuiltin_tbb=ON ^ -Dbuiltin_unuran=ON ^ -Dbuiltin_freetype=ON ^ -Dbuiltin_pcre=ON ^ -Dbuiltin_zlib=ON ^ -Dbuiltin_lz4=ON ^ -Dbuiltin_lzma=ON ^ -Dbuiltin_xxhash=ON ^ -Dbuiltin_imt=ON ^ -Dbuiltin_vc=ON ^ -Dbuiltin_clang=ON ^ -Dbuiltin_davix=ON ^ -Dbuiltin_gsl=OFF ^ # 如果系统有GSL,可以设为OFF -Dbuiltin_cfitsio=ON ^ -Dbuiltin_pythia6=OFF ^ -Dbuiltin_pythia8=ON ^ -Dbuiltin_fftw3=ON ^ -Dbuiltin_openssl=ON ^ -Dbuiltin_curl=ON ^ -Dbuiltin_tbb=ON ^ -Dxrootd=OFF ^ -Dgdml=ON ^ -Dminuit2=ON ^ -Droofit=ON ^ -Dtmva=ON ^ -Dpyroot=ON ^ -DCMAKE_CXX_STANDARD=17 ^ -DCMAKE_BUILD_TYPE=Release ^ -G "Visual Studio 16 2019" -A x64 .. ``` 注意:上述选项根据实际需要调整,目的是尽可能使用内置库(builtin)以避免外部依赖问题。 #### 方法3:使用正确的依赖扫描工具 1. **使用`windeployqt`**:确保使用与Qt版本匹配的`windeployqt`工具。在命令行中运行: ```batch windeployqt --release --compiler-runtime --no-angle --no-opengl-sw your_app.exe ``` 注意:`--compiler-runtime`选项会复制VC++运行时库,但不会复制系统API Set的虚拟DLL,所以这个错误可能不会通过此方法解决。 2. **手动处理依赖**: - 使用Visual Studio自带的`dumpbin`工具检查依赖: ```batch dumpbin /DEPENDENTS your_app.exe ``` 查看是否有对`ext-ms-win32-subsystem-query-l1-1-0.dll`的引用。正常情况下,这个引用会被系统自动重定向,不应该导致缺失错误。 - 如果发现其他实际存在的DLL缺失,请手动复制它们到应用程序目录。 #### 方法4:使用AppCRT(应用CRT)打包 对于Visual Studio 2015及更高版本,建议使用应用本地部署(即将VC++运行时库复制到应用程序目录): 1. 在打包目录中包含以下VC++运行时DLL(根据编译时使用的CRT版本选择): - `vcruntime140.dll`(VS2015-2022都有使用) - `vcruntime140_1.dll`(VS2019和VS2022需要) - `msvcp140.dll` - `concrt140.dll` - 以及其他可能需要的CRT DLL。 这些文件通常位于: ``` C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\ ``` 注意:版本号(`14.29.30133`)可能不同。 2. 使用官方提供的合并模块(Merge Modules)或通过安装可再发行组件包(Redistributable Package)解决,但在打包独立应用时,推荐本地部署。 #### 方法5:忽略虚拟DLL依赖 由于`ext-ms-win32-subsystem-query-l1-1-0.dll`是虚拟的,实际上不需要打包。如果错误来自依赖扫描工具(如Dependency Walker)的误报,可以忽略它。但是,如果应用程序在运行时确实出现缺失该DLL的错误,则可能是目标系统版本太低(如Windows 7),此时需要: 1. 在应用程序的清单文件中指定支持的操作系统版本(`application.manifest`): ```xml <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows 10 and Windows 11 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> </application> </compatibility> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> </assembly> ``` 2. 确保应用程序在支持API Set的操作系统上运行(Windows 10 1607及以上)。 ### 打包建议 1. 创建一个应用程序目录,包含: - `your_app.exe` - Qt相关的DLL(由`windeployqt`自动复制) - ROOT核心DLL(手动复制,如`libCore.dll`等) - VC++运行时DLL(如`vcruntime140.dll`等) - 启动脚本`run.bat`(用于设置ROOT环境) 2. 启动脚本示例(`run.bat`): ```batch @echo off set ROOTSYS=%~dp0root set PATH=%~dp0;%ROOTSYS%\bin;%PATH% your_app.exe ``` 3. 目录结构示例: ``` Application/ ├── your_app.exe ├── Qt5Core.dll ├── ... (其他Qt DLL) ├── libCore.dll ├── ... (其他ROOT DLL) ├── vcruntime140.dll ├── ... (其他CRT DLL) ├── root/ │ ├── bin/ │ ├── etc/ │ └── ... (其他必要的ROOT目录) └── run.bat ``` ### 常见问题排查 - **错误:无法定位程序输入点于动态链接库**:这通常是因为DLL版本不匹配,尤其是VC++运行时库版本不匹配。确保打包的CRT DLL与编译时使用的版本一致。 - **ROOT初始化失败**:检查`ROOTSYS`环境变量是否指向正确的目录,并确保`root/etc`目录存在且包含配置文件。 ### 引用 在解决Windows API Set相关问题时,参考了微软的官方文档[^1]和ROOT论坛的相关讨论[^2]。 §§相关问题§§ 1. 如何确定应用程序依赖的所有DLL? 2. 如何为Windows应用程序创建安装程序? 3. 如何解决Qt应用程序在Windows上的高DPI缩放问题? 4. 如何将ROOT的TCanvas嵌入到Qt的QWidget中? [^1]: [Microsoft API Sets](https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-apisets) [^2]: [ROOT Forum: Windows support status](https://root-forum.cern.ch/t/windows-support-status/48021)</think>### 解决Windows打包Qt与ROOT应用时出现的DLL错误 #### 问题分析 错误信息 `QueryWin32SubsystemHost ext-ms-win32-subsystem-query-l1-1-0.dll` 表明: 1. 系统缺失Windows子系统API扩展库(虚拟DLL) 2. ROOT/Qt调用了新版Windows API但目标系统版本过低 3. 依赖扫描工具未能正确处理API Set映射机制[^1] --- ### 解决方案 #### 方法1:更新Windows SDK和运行时库 ```batch :: 安装最新VC++运行时库 curl -LO https://aka.ms/vs/17/release/vc_redist.x64.exe vc_redist.x64.exe /install /quiet /norestart :: 更新Windows 10 SDK (需Visual Studio) :: 在VS安装器中勾选"Windows 10 SDK (10.0.19041.0)" ``` #### 方法2:修正ROOT编译配置 在编译ROOT时添加CMake选项: ```cmake cmake -DCMAKE_INSTALL_PREFIX=C:/root ^ -Dbuiltin_llvm=ON ^ -Druntime_cxxmodules=OFF ^ -Dminimal=ON ^ # 仅包含核心模块 -DCMAKE_SYSTEM_VERSION=10.0.17763.0 # 指定Win10 SDK版本 ``` #### 方法3:手动处理API Set依赖 1. **查找实际依赖**: ```batch dumpbin /DEPENDENTS your_app.exe | findstr /i "ext-ms-win" ``` 2. **创建API Set映射文件**(`yourapp.manifest`): ```xml <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v3"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df"/> </dependentAssembly> </dependency> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- 声明支持Windows 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> </application> </compatibility> </assembly> ``` 3. **嵌入清单文件**: ```batch mt.exe -manifest yourapp.manifest -outputresource:your_app.exe;1 ``` #### 方法4:使用依赖打包工具 1. 通过[Windows API Sets Viewer](https://github.com/zer0condition/API-Sets)识别实际DLL 2. 在打包目录中包含以下关键库: ``` api-ms-win-core-sysinfo-l1-2-1.dll → kernel32.dll api-ms-win-core-processthreads-l1-1-2.dll → kernel32.dll ext-ms-win-ntuser-message-l1-1-0.dll → user32.dll ``` 3. 使用增强版部署工具: ```batch windeployqt --release --no-api-sets-renaming your_app.exe ``` --- ### 完整打包流程 ```mermaid graph TD A[编译应用] --> B[收集Qt依赖] B --> C[收集ROOT核心DLL] C --> D[添加API Set映射] D --> E[嵌入清单文件] E --> F[测试运行] F --> G[制作安装包] ``` #### 关键文件清单 | 类型 | 必需文件 | 来源 | |------|----------|------| | **Qt** | Qt5Core.dll, Qt5Gui.dll, Qt5Widgets.dll | windeployqt生成 | | **ROOT** | libCore.dll, libTree.dll, libGraf.dll | ROOT安装目录/bin | | **Windows** | vcruntime140.dll, msvcp140.dll | VC_redist目录 | | **API代理** | api-ms-win-*.dll | Windows SDK/10/UnionMetadata | --- ### 验证方法 在纯净Windows虚拟机中测试: ```batch set ROOTSYS=C:\your_app\root set PATH=C:\your_app\bin;%ROOTSYS%\bin;%PATH% your_app.exe ``` > **注意**:若目标系统为Windows 7,需强制ROOT使用兼容模式: > ```cpp > ROOT::EnableThreadSafety(); > gSystem->Setenv("ROOT_WIN7_COMPAT", "1"); > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值