Digits of Factorial (求N!的k进制位数)(打表)

本文介绍了一种使用预计算对数表的方法来解决特定问题的技术。通过预先计算并存储一系列对数值,可以在运行时快速得出结果,避免了直接计算带来的效率问题。这种方法适用于需要频繁查询对数值的应用场景。

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

很久以前的一个周练上写过这道题,主要思路就是用对数,用一开始连续的对数相加再除以K进制的对数就可以求出来 ,不过这个题会超时,所以打个表用空间换时间

#include<stdio.h>
#include<math.h>
double arr[1000000 +10];

void biao()
{
	double d = 0;
	arr[0] = 0;
	for(int i = 1;i < 1000010;i ++){
		d += log(i);
		arr[i] = d;
	}
}
int main()
{
	biao();
	int T,k=0;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d%d",&n,&m);
		printf("Case %d: %d\n",++k,(int)(arr[n]/log(m))+1);
	}
return 0;
}


#include <iostream> #include <string> #include <chrono> #include <iomanip> #include <thread> #include <vector> #include <cmath> #include <fstream> #include <sstream> #include <cstdlib> #include <atomic> #include <mutex> #ifdef _WIN32 #include <windows.h> #include <psapi.h> #include <d3d11.h> #include <dxgi.h> #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "dxgi.lib") #else #include <sys/sysinfo.h> #include <unistd.h> #endif using namespace std; // 系统资源监控结构体 struct SystemResources { double cpu_usage; double gpu_usage; long memory_used; long memory_total; long memory_available; }; // 全局变量用于线程控制 atomic<bool> running(true); mutex data_mutex; string current_pi_value = "3"; int current_precision = 0; // 高性能π计算算法 (Chudnovsky算法) class PiCalculator { private: // Chudnovsky算法常数 const double kC = 640320.0; const double kC3_24 = kC * kC * kC / 24.0; // 精度计算参数 int precision; int terms; public: PiCalculator(int prec) : precision(prec) { // 根据所需精度计算需要的项数 terms = static_cast<int>(log10(kC3_24) * precision / 3) + 1; } int get_precision() const { return precision; } string calculate() { double sum = 0.0; double term; double factorial = 1.0; double sign = 1.0; // Chudnovsky算法实现 for (int k = 0; k < terms; ++k) { if (k > 0) { factorial *= (6.0 * k) * (6.0 * k - 1) * (6.0 * k - 2) * (6.0 * k - 3) * (6.0 * k - 4) * (6.0 * k - 5); factorial /= (3.0 * k) * (3.0 * k - 1) * (3.0 * k - 2) * pow(k, 3.0); sign *= -1; } term = (13591409.0 + 545140134.0 * k) * factorial; term *= sign; term /= pow(kC3_24, k + 0.5); sum += term; } double pi = 1.0 / (12.0 * sum); stringstream ss; ss << fixed << setprecision(precision) << pi; string result = ss.str(); // 确保格式正确,以3.开头 size_t dot_pos = result.find('.'); if (dot_pos != string::npos) { result = "3." + result.substr(dot_pos + 1); } else { result = "3.0"; } return result; } void update_precision(int new_precision) { precision = new_precision; terms = static_cast<int>(log10(kC3_24) * new_precision / 3) + 1; } }; #ifdef _WIN32 double get_gpu_usage() { return 0.0; // 简化处理 } #endif SystemResources get_system_resources() { SystemResources res{}; #ifdef _WIN32 // Windows CPU使用率计算 static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU; static int numProcessors = 0; static HANDLE self = GetCurrentProcess(); if (numProcessors == 0) { SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo); numProcessors = sysInfo.dwNumberOfProcessors; } FILETIME ftime, fsys, fuser; ULARGE_INTEGER now, sys, user; GetSystemTimeAsFileTime(&ftime); memcpy(&now, &ftime, sizeof(FILETIME)); GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser); memcpy(&sys, &fsys, sizeof(FILETIME)); memcpy(&user, &fuser, sizeof(FILETIME)); double percent = (sys.QuadPart - lastSysCPU.QuadPart) + (user.QuadPart - lastUserCPU.QuadPart); percent /= (now.QuadPart - lastCPU.QuadPart); percent /= numProcessors; res.cpu_usage = min(100.0, max(0.0, percent * 100)); lastCPU = now; lastUserCPU = user; lastSysCPU = sys; // 内存使用情况 MEMORYSTATUSEX memInfo; memInfo.dwLength = sizeof(MEMORYSTATUSEX); if (GlobalMemoryStatusEx(&memInfo)) { res.memory_total = memInfo.ullTotalPhys / (1024 * 1024); res.memory_available = memInfo.ullAvailPhys / (1024 * 1024); res.memory_used = res.memory_total - res.memory_available; } res.gpu_usage = get_gpu_usage(); #else // Linux CPU使用率计算 static unsigned long long lastTotalUser = 0, lastTotalUserLow = 0, lastTotalSys = 0, lastTotalIdle = 0; FILE* file = fopen("/proc/stat", "r"); if (file) { unsigned long long totalUser, totalUserLow, totalSys, totalIdle; if (fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, &totalSys, &totalIdle) == 4) { if (lastTotalUser != 0) { unsigned long long total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + (totalSys - lastTotalSys); unsigned long long totalIdleDiff = totalIdle - lastTotalIdle; unsigned long long totalUsed = total - totalIdleDiff; if (total > 0) { res.cpu_usage = (100.0 * totalUsed) / total; } } lastTotalUser = totalUser; lastTotalUserLow = totalUserLow; lastTotalSys = totalSys; lastTotalIdle = totalIdle; } fclose(file); } // Linux内存使用情况 struct sysinfo memInfo; if (sysinfo(&memInfo) == 0) { res.memory_total = memInfo.totalram * memInfo.mem_unit / (1024 * 1024); res.memory_available = memInfo.freeram * memInfo.mem_unit / (1024 * 1024); res.memory_used = res.memory_total - res.memory_available; } res.gpu_usage = 0.0; #endif return res; } void display_thread_func() { auto start_time = chrono::high_resolution_clock::now(); int iteration = 0; while (running) { iteration++; SystemResources res = get_system_resources(); string pi_value; int digits_calculated; { lock_guard<mutex> lock(data_mutex); pi_value = current_pi_value; digits_calculated = current_precision; } // 准备显示内容 stringstream display; display << "π: " << pi_value << "\n\n"; display << "CPU: " << fixed << setprecision(1) << res.cpu_usage << "%\n"; display << "GPU: " << fixed << setprecision(1) << res.gpu_usage << "%\n"; if (res.memory_total > 1024) { display << "内存: " << fixed << setprecision(1) << res.memory_used / 1024.0 << "GB/" << res.memory_total / 1024.0 << "GB (可用: " << res.memory_available / 1024.0 << "GB)\n"; } else { display << "内存: " << res.memory_used << "MB/" << res.memory_total << "MB (可用: " << res.memory_available << "MB)\n"; } display << "\n迭代次数: " << iteration << "\n"; auto current_time = chrono::high_resolution_clock::now(); double elapsed_seconds = chrono::duration_cast<chrono::duration<double>>(current_time - start_time).count(); double digits_per_second = digits_calculated / max(1.0, elapsed_seconds); display << "计算速度: " << fixed << setprecision(2) << digits_per_second << " 位/秒\n"; display << "已计算位数: " << digits_calculated << "\n"; system("clear || cls"); cout << display.str(); this_thread::sleep_for(chrono::milliseconds(500)); } } void calculation_thread_func() { PiCalculator calculator(2); // 初始精度 while (running) { string pi_value = calculator.calculate(); int precision = calculator.get_precision(); { lock_guard<mutex> lock(data_mutex); current_pi_value = pi_value; current_precision = precision; } // 逐步增加精度 int new_precision = min(precision * 2, 1000000); calculator.update_precision(new_precision); this_thread::sleep_for(chrono::milliseconds(100)); } } int main() { cout << "启动高性能π计算器..." << endl; cout << "使用Chudnovsky算法计算π" << endl; cout << "正在初始化..." << endl; this_thread::sleep_for(chrono::seconds(1)); try { thread display_thread(display_thread_func); thread calculation_thread(calculation_thread_func); cout << "按任意键停止计算..." << endl; cin.get(); running = false; display_thread.join(); calculation_thread.join(); cout << "\n计算已停止。" << endl; } catch (const exception& e) { cerr << "程序出错: " << e.what() << endl; return 1; } return 0; } 修改代码,使其可以正常的显示已计算的π位数和值,且可以正常的显示 CPU,内存 和 GPU 的使用率或占用大小,正确的使用内存,CPU 和 GPU,确保可以正常使用且可以打好配合 不在乎代码的工程量和长短,只追完美的效果
07-25
#include <iostream> #include <cmath> #include <chrono> #include <thread> #include <vector> #include <gmpxx.h> #include <fstream> #include <sstream> #include <iomanip> #include <mutex> #include <atomic> #include <sys/sysinfo.h> #include <sys/resource.h> #include <fstream> #include <unistd.h> #include <nvml.h> // NVIDIA GPU监控 std::mutex output_mutex; std::atomic<bool> stop_monitor(false); mpf_class pi_value(0, 0); // 高精度π值 std::atomic<int> iteration_count(0); // 获取CPU使用率 double get_cpu_usage() { static uint64_t last_total = 0, last_idle = 0; std::ifstream stat_file("/proc/stat"); std::string line; std::getline(stat_file, line); std::istringstream iss(line); std::string cpu; uint64_t user, nice, system, idle, iowait, irq, softirq, steal; iss >> cpu >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal; uint64_t total = user + nice + system + irq + softirq + steal; uint64_t idle_time = idle + iowait; double usage = 0.0; if (last_total != 0) { uint64_t total_diff = total - last_total; uint64_t idle_diff = idle_time - last_idle; usage = 100.0 * (1.0 - static_cast<double>(idle_diff) / total_diff); } last_total = total; last_idle = idle_time; return usage; } // 获取内存使用率 double get_memory_usage() { struct sysinfo mem_info; sysinfo(&mem_info); double total = mem_info.totalram; double free = mem_info.freeram; return 100.0 * (1.0 - free / total); } // 获取GPU使用率 (NVIDIA) double get_gpu_usage() { nvmlReturn_t result; nvmlDevice_t device; unsigned int utilization; result = nvmlInit(); if (result != NVML_SUCCESS) return -1.0; result = nvmlDeviceGetHandleByIndex(0, &device); if (result != NVML_SUCCESS) { nvmlShutdown(); return -1.0; } result = nvmlDeviceGetUtilizationRates(device, &utilization); if (result != NVML_SUCCESS) { nvmlShutdown(); return -1.0; } nvmlShutdown(); return static_cast<double>(utilization.gpu); } // 资源监控线程函数 void monitor_resources() { while (!stop_monitor) { double cpu = get_cpu_usage(); double mem = get_memory_usage(); double gpu = get_gpu_usage(); { std::lock_guard<std::mutex> lock(output_mutex); std::cout << "\033[2K"; // 清除当前行 std::cout << "\r[资源监控] CPU: " << std::fixed << std::setprecision(1) << cpu << "% | " << "内存: " << mem << "% | " << "GPU: " << (gpu >= 0 ? std::to_string(static_cast<int>(gpu)) + "%" : "N/A"); std::cout.flush(); } std::this_thread::sleep_for(std::chrono::seconds(1)); } } // Chudnovsky算法计算π mpf_class chudnovsky_pi(unsigned int precision, unsigned int iterations) { mpf_set_default_prec(precision); mpf_class pi(0, precision); mpf_class sum(0, precision); mpf_class k1(13591409, precision); mpf_class k2(545140134, precision); mpf_class k3(-262537412640768000, precision); mpf_class k4(426880, precision); mpf_class k5(10005, precision); mpf_class sqrt_c(0, precision); k5 = sqrt(k5); sqrt_c = k4 * k5; mpz_class a(1); mpz_class b(1); mpz_class a_prime(1); mpz_class b_prime(1); for (unsigned int k = 0; k < iterations; k++) { mpf_class numerator(0, precision); mpf_class denominator(0, precision); if (k == 0) { a = 1; b = 1; } else { // 使用二进制分裂法优化计算 a_prime = (6*k-5)*(2*k-1)*(6*k-1); b_prime = k*k*k * k3 / 24; a *= a_prime; b *= b_prime; } numerator = k1 + k2 * k; denominator = a * b; sum += numerator / denominator; iteration_count = k + 1; // 每100次迭代显示进度 if (k % 100 == 0) { pi = sqrt_c / sum; std::lock_guard<std::mutex> lock(output_mutex); std::cout << "\n[计算进度] 迭代: " << k << "/" << iterations << " | 当前π值: " << std::setprecision(15) << pi << std::endl; } } pi = sqrt_c / sum; return pi; } int main() { const unsigned int precision = 100000; // 二进制精度位 const unsigned int iterations = 1000; // 迭代次数 std::cout << "开始计算π值 (Chudnovsky算法)..." << std::endl; std::cout << "精度: " << precision << "位 | 最大迭代: " << iterations << std::endl; // 启动资源监控线程 std::thread monitor_thread(monitor_resources); // 记录开始时间 auto start_time = std::chrono::high_resolution_clock::now(); // 计算π值 pi_value = chudnovsky_pi(precision, iterations); // 记录结束时间 auto end_time = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time); // 停止监控线程 stop_monitor = true; monitor_thread.join(); // 输出最终结果 std::cout << "\n\n计算完成!" << std::endl; std::cout << "耗时: " << duration.count() / 1000.0 << " 秒" << std::endl; std::cout << "最终π值(前50位): " << std::setprecision(50) << pi_value << std::endl; return 0; } 修复代码错误 default.cpp:6:10: fatal error: 'gmpxx.h' file not found #include <gmpxx.h> ^~~~~~~~~ 1 error generated.
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值