第四届传智杯全国大学生IT技能大赛 初赛B组题解 -- D题

题目:小卡与质数2

Description

小卡最近迷上了质数,所以他想把任何一个数都转化为质数!
小卡有 T 次询问,每次给你一个数字 x,问有多少个比 x 小的非负整数 y,使得 x⊕y 是质数,其中 ⊕ 表示按位异或。

Input

第一行一个正整数 T(1≤T≤105),表示有 T 组询问。
接下来 T 行,每行一个正整数 x(1≤x≤106)。

Output

对于每组询问,输出一行一个整数,表示答案。

Sample

输入

9
5
6
7
8
9
10
100
1000
10000

输出

2
4
4
2
2
4
22
163
1132

Solution
  1. 非负整数 x 与小于自身的非负整数异或得到的结果都不相同
  2. 非负整数 x 与小于自身的非负整数异或得到的结果必定小于 2x
  3. 非负整数 x = (1000…000)2 与小于自身的非负整数异或,值域为[1000…000, 1111…111],即[x, x2-1],例:x = 4 = (100)2
  4. 非负整数 x = (1xxx…xxx)2 与小于(1000…000)2的非负整数异或,[1000…000, 1111…111]是值域的子集,即[x, x2-1]是值域的子集,例:x = 6 = (110)2
  5. 非负整数 x 与小于自身的非负整数异或,若 x 的二进制数在某位上为1,如(…1…),那么[0001000, 0001111]是值域的子集

通过二进制枚举 x 的每一个位,求出各个值域子集内质数的个数之和。

例子:
x = 6 = (110)2
110 ^ 000 = 110 = 6
110 ^ 001 = 111 = 7
110 ^ 010 = 100 = 4
110 ^ 011 = 101 = 5

110 ^ 100 = 010 = 3
110 ^ 101 = 011 = 2
菜鸡不会严格的证明:(大家有什么其他好的方法也欢迎分享

AC Code
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;

const int M = 5000001;
int a[M] = {0};
//判断是否为素数
bool prime(int num) {
	if (num == 1)
		return 0;
	if (num == 2 || num == 3)
		return 1;
	if (num % 6 != 1 && num % 6 != 5)
		return 0;
	int tmp = sqrt(num);
	for (int i = 5; i <= tmp; i += 6)
		if (num % i == 0 || num % (i + 2) == 0)
			return 0;
	return 1;
}

int main() {
	// a[i] 表示[1, i]内质数的个数
    for(int i = 1; i <= M; i++) {
        a[i] = a[i-1];
        if(prime(i)) {
            ++ a[i];
        }
    }
    int t;
    cin >> t;
    while(t--) {
        int num = 0;
        int x;
        cin >> x;
        // 二进制枚举
        int f = 1;
        while(f <= x) {
            int ls = f & x;
            // cout << "f = " << f << " x = " << x;
            // cout << "ls = " << ls << endl;
            if(ls > 0) {
                int rs = (ls << 1);
                num += a[rs-1] - a[ls-1];
            }
            f <<= 1;
        }
        cout << num << endl;
    }
    return 0;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第六届传智杯B初赛是传智播客举办的一次IT技术竞赛的初赛阶段,旨在选拔出各高校优秀的程序设计人才。该比赛中,参赛者将面临多道编程目,通过编写程序解决问题来展示他们的技术水平和创新能力。 在初赛中,参赛者需要在规定的时间内完成多道程序设计目。这些目可能涉及数据结构、算法、网络通信等方面的知识,要求参赛者具备扎实的编程基础和解决实际问题的能力。 参赛者需要在规定的时间内完成编程目,并提交给评委进行评分。评委会根据答案的正确性、效率、代码的可读性等方面对参赛者的作品进行综合评判。最终,得分高的参赛者将进入下一轮比赛。 第六届传智杯B初赛的目的是为了选拔出具备优秀编程能力的学生,为他们提供一个展示才华、学习交流的平台。参赛者不仅可以通过比赛锻炼自己的编程技巧,还可以结识其他优秀的参赛者,相互学习、切磋技艺。 在比赛过程中,参赛者还可以通过与其他选手交流,了解各种不同的编程思路和解方法,不断提高自己的编程水平。同时,参赛者还有机会与业界的专家学者进行交流,了解最新的技术动态和发展趋势。 总之,第六届传智杯B初赛是一次很有意义的编程竞赛,为各大高校的IT人才选拔提供了一次难得的机会。通过比赛,参赛者可以展现自己的才华,提升技术水平,同时也可以与其他优秀选手进行交流,共同进步。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值