• 【牛客网】牛客练习赛19 F 算式子【数学--递推 、前缀、数字】


    传送门:算式子

    花了一些时间理解AC的代码,震惊,代码真的是短小精悍,推理能力很强亦或者是做题多,见的多。
    能够理解里面的逻辑真的挺难的

    题意

    给定n,m,(1le xle m),求(sum_{i=1}^n{( ⌊frac {a_i} {x} ⌋ +⌊ frac {x} {a_i} ⌋ )})

    分析

    介绍一下用到的变量。
    初始时

    a数组存放值
    cnt[i]表示i出现的次数
    bkt[i]储存结果
    

    求和分为两部分,分开求解。

    part1: (sum_{i=1}^n{( ⌊frac {a_i} {x} ⌋ )})

    首先预处理cnt数组,处理后 cnt[i] 表示a数组中 >= i的数字有多少个。
    然后求他们的后缀和(很神奇!)

    part2: (sum_{i=1}^n{( ⌊frac {x} {a_i} ⌋ )})

    bkt[i+1]储存i能够整除元素(a数组)的数量

    i bkt[i] 储存的值
    1 2 1 1
    2 3 1 1 2
    3 4 1 1 3 3
    4 3 1 1 2
    5 5 1 1 5 5 5
    6 5 11 2 3 3
    7 2 1 1

    求前缀和,具体为什么可以这样做(我也不知道啊,但是带进去算确实是对的)

    Online AC Code

    /*
    参考:https://www.nowcoder.com/acm/contest/view-submission?submissionId=36414030
    镇海中学 __asm
    寥寥数行,其中蕴含了很强的推理知识,对前缀、数字有很好的掌握
    佩服佩服,高中生牛逼
    */
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    #define MAXN 5000010
    typedef long long lnt;
    
    int n, m;
    lnt bkt[MAXN], cnt[MAXN], ans;
    int main()
    {
    	scanf("%d%d", &n, &m);
    	// cnt x的出现次数
    	for (int i = 1, x; i <= n; i++) scanf("%d", &x), cnt[x]++;
    	
    	cout<<"cnt: "<<endl;
    	for(int i=1;i<=m;i++) cout<<cnt[i]<<" "; cout<<endl;
    	
    	// 储存第二部分的结果??
    	for (int i = 1; i <= m; i++)
    		for (int j = i; j <= m; j += i) bkt[j] += cnt[i];
    		
    
    	for(int i=1;i<=m;i++)
    		cout<<bkt[i]<<" ";
    	cout<<endl;
    	
    	// 前缀和?
    	for (int i = 1; i <= m; i++) bkt[i] += bkt[i - 1];
    	
    	for(int i=1;i<=m;i++) cout<<bkt[i]<<" "; cout<<endl;
    
    	// 预处理第一部分?
    	// 处理后 cnt[i] 表示>= i的数字有多少个。
    	for (int i = m; i; i--) cnt[i] += cnt[i + 1];
    	
    	cout<<"cnt: "<<endl;
    	for(int i=1;i<=m;i++) cout<<cnt[i]<<" "; cout<<endl;
    
    	// 计算第一部分的结果?
    	for (int i = 1; i <= m; i++)
    		for (int j = i; j <= m; j += i)
    			bkt[i] += cnt[j];
    		
    	for(int i=1;i<=m;i++) cout<<bkt[i]<<" "; cout<<endl;
    
    	// 计算结果?
    	for (int i = 1; i <= m; i++)
    		ans ^= bkt[i];	
    	
    
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    采购订单打印并预览PDF
    KiCad 如何在原理图添加元件时看到 PCB 封装?
    KiCad 开源元件库收集 (2019-05-31)
    KiCad 的 Digikey 元件库
    MySQL 出现 Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
    AD10 没有原理图是否可以修改 PCB
    KiCad 如何画板框
    当 1117 遇到 MLCC 后
    RequireJS 学习资料收集
    MEMS 硅麦资料收集
  • 原文地址:https://www.cnblogs.com/shengwang/p/9844726.html
Copyright © 2020-2023  润新知