zoukankan      html  css  js  c++  java
  • [BZOJ2440][中山市选2011]完全平方数

    [BZOJ2440][中山市选2011]完全平方数

    试题描述

    小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而这丝毫不影响他对其他数的热爱。 
    这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了小X。小X很开心地收下了。 
    然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?

    输入

    包含多组测试数据。文件第一行有一个整数 T,表示测试数据的组数。
    第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。

    输出

    含T 行,分别对每组数据作出回答。第 i 行输出相应的第Ki 个不是完全平方数的正整数倍的数。

    输入示例

    4
    1
    13
    100
    1234567

    输出示例

    1
    19
    163
    2030745

    数据规模及约定

    对于 100%的数据有 1 ≤ Ki ≤ 10^9,T ≤ 50

    题解

    先二分答案 x,问题转化成求 [1, x] 中有多少个不包含完全平方因子的数。我们令这个完全平方因子为 t2,那么我们就可以容斥,t 含 0 个不同质因数情况 - t 含 1 个不同质因数情况 + t 含 2 个不同质因数情况 ...,于是莫比乌斯函数提供了一个天然的容斥的系数。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 1000001
    
    int prime[maxn], cnt, mu[maxn];
    bool vis[maxn];
    void init() {
    	mu[1] = 1;
    	for(int i = 2; i < maxn; i++) {
    		if(!vis[i]) prime[++cnt] = i, mu[i] = -1;
    		for(int j = 1; prime[j] * i < maxn && j <= cnt; j++) {
    			vis[prime[j]*i] = 1;
    			if(i % prime[j] == 0) { mu[prime[j]*i] = 0; break; }
    			mu[prime[j]*i] = -mu[i];
    		}
    	}
    	return ;
    }
    
    int calc(int x) {
    	int m = sqrt(x + .5), res = 0;
    	for(int i = 1; i <= m; i++) res += x / (i * i) * mu[i];
    	return res;
    }
    
    int main() {
    	init();
    	
    	int T = read();
    	while(T--) {
    		int K = read(),  l = 1, r = 2000000000;
    		while(l < r) {
    			int mid = l + (r - l >> 1);
    			if(calc(mid) < K) l = mid + 1; else r = mid;
    		}
    		printf("%d
    ", l);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    解析大型.NET ERP系统 权限模块设计与实现
    Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架
    解析大型.NET ERP系统 单据编码功能实现
    解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计
    Windows 10 部署Enterprise Solution 5.5
    解析大型.NET ERP系统 设计异常处理模块
    解析大型.NET ERP系统 业务逻辑设计与实现
    解析大型.NET ERP系统 多国语言实现
    Enterprise Solution 管理软件开发框架流程实战
    解析大型.NET ERP系统 数据审计功能
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7091562.html
Copyright © 2011-2022 走看看