• 第四届传智杯初赛_小卡与质数2


    [传智杯 #4 初赛] 小卡与质数2

    题目背景

    小卡迷上了质数!

    题目描述

    小卡最近迷上了质数,所以他想把任何一个数都转化为质数!

    小卡有 T T T 次询问,每次给你一个数字 x x x,问有多少个比 x x x 小的非负整数 y y y,使得 x ⊕ y x\oplus y xy 是质数,其中 ⊕ \oplus 表示按位异或

    输入格式

    第一行一个正整数 T ( 1 ≤ T ≤ 1 0 5 ) T(1\le T\le10^5) T(1T105),表示有 T T T 组询问。

    接下来 T T T 行,每行一个正整数 x ( 1 ≤ x ≤ 1 0 6 ) x(1\le x\le 10^6) x(1x106)

    输出格式

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

    样例 #1

    样例输入 #1

    9
    5
    6
    7
    8
    9
    10
    100
    1000
    10000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    样例输出 #1

    2
    4
    4
    2
    2
    4
    22
    163
    1132
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    算法(思维,二进制,素数筛,前缀和)

    x ⊕ y = p ( y < x ) x⊕y=p (y < x) xy=p(y<x)
    要枚举 y y y,时间复杂度 O ( T x ) O(Tx) O(Tx)
    x ⊕ y = p → x ⊕ p = y ( y < x ) x⊕y=p \to x⊕p=y(y < x) xy=pxp=y(y<x)
    要枚举 p p p ,时间复杂度 O ( T z ) O(Tz) O(Tz) 。百万内的质数有 z z z个(几万)。
    因为 y < x yy<x,异或后值变小。什么情况异或后值会变小?
    x = ( 100100 ) 2 x=(100100)_2 x=(100100)2
    要想异或后值变小, 1 1 1必须变成 0 0 0

    1 ⊕ 1 = 0 1⊕1=0 11=0

    • 第一个 1 1 1
      100100 ⊕ 1 ∗ ∗ ∗ ∗ ∗ = 0 ∗ ∗ ∗ ∗ ∗ < 100100 100100⊕ 1***** = 0***** <100100 1001001=0<100100
      换言之, 100100 ⊕ ( 100000 ∼ 111111 ) 100100⊕(100000 \sim 111111) 100100(100000111111)的值都小于 100100 100100 100100
      即, x ⊕ ( 2 5 ∼ 2 6 − 1 ) x⊕(2^5 \sim 2^6-1) x(25261)
      的值小于 x x x
      现在我们只要算出 ( 2 5 ∼ 2 6 − 1 ) (2^5 \sim 2^6-1) (25261)
      有几个质数即可,前缀和。

    • 第二个 1 1 1
      100100 ⊕ 0001 ∗ ∗ = 1000 ∗ ∗ < 100100 100100 ⊕ 0001** = 1000** <100100 1001000001=1000<100100
      换言之, 100100 ⊕ ( 000100 ∼ 000111 ) 100100⊕(000100 \sim 000111) 100100(000100000111) 的值都小于 100100 100100 100100
      即, x ⊕ ( 2 2 ∼ 2 3 − 1 ) x⊕(2^2 \sim 2^3-1) x(22231)
      的值小于 x x x
      现在我们只要算出 ( 2 2 ∼ 2 3 − 1 ) (2^2 \sim 2^3-1) (22231) 有几个质数即可。

    总之,若 x x x 的第 i i i 位为 1 1 1,算出 2 i ∼ 2 i + 1 − 1 2^i \sim 2^{i+1}-1 2i2i+11有多少个质数累加即可。

    注意, x ⊕ p = y ( y < x ) x⊕p=y(y < x) xp=y(y<x) p p p 有可能超过 x x x

    代码(C++)

    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 2e6 + 10;
    
    bool st[N];
    int s[N];
    
    int lowbit(int x)
    {
    	return x & -x;
    }
    
    void get_prefix()
    {
    	st[0] = st[1] = 1;
    	for(int i = 2; i <= N - 10; i ++)
    	{
    		if(st[i]) continue;
    		for(int j = i + i; j <= N - 10; j += i) st[j] = 1;
    	}
    	
    	for(int i = 1; i <= N - 10; i ++) s[i] = s[i - 1] + (!st[i]);
    }
    
    int main()
    {
    	
    	get_prefix();
    	
    	int T;
    	scanf("%d", &T);
    	while(T --)
    	{
    		int x;
            scanf("%d", &x);
            
            int res = 0;
            while(x)
            {
            	int t = lowbit(x);
            	res += s[(t << 1) - 1] - s[t - 1];
    			x -= t;
    		}
    		cout << res << endl;
    	}
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
  • 相关阅读:
    五种实现数据加密存储的方式,你选择哪一种
    【开发】安防监控/视频汇聚/云存储/AI智能视频融合平台页面新增地图模式
    AI项目十三:PaddleOCR训练自定义数据集
    C++ 环境变量 二
    独立app开发和运行(使用篇)
    [附源码]计算机毕业设计JAVA高校资源共享平台
    MMdetection训练配置
    java使用smiley-http-proxy-servlet实现反向代理,跳过SSL认证
    后端不提供文件流接口,前台js使用a标签实现当前表格数据(数组非blob数据)下载成Excel
    Kibana Query Language (KQL)
  • 原文地址:https://blog.csdn.net/zygood_/article/details/127883393