• The 2018 ICPC Asia Nanjing Regional J


    原文链接

    The 2018 ACM-ICPC Asia Nanjing Regional Programming Contest J - Prime Game

    [题目传送门](Attachments - 2018-2019 ACM-ICPC, Asia Nanjing Regional Contest - Codeforces)


    题目描述

    the problem

    题目解析

    题目的意思实际上是求每个子区间的乘积总共有多少个不同的质因数

    在这里需要用到贡献度的思想,具体可以参考这两篇文章:

    Beauty of Array(贡献度思想)_pioneer1-CSDN博客

    贡献思想 + 数论 + 思维(例题 Problem J. Prime Game)_qq_41818544的博客-CSDN博客

    其实第二篇就是别人写的本题的题解

    由于之前没有接触过贡献度的思想,所以本蒟蒻根本做不出这道题qwq

    本题要求每个子区间的乘积总共有多少个不同的质因数,所以可以从单个元素入手,求出这个元素的质因数,然后确定有多少个区间包含了这个元素,之后记录这个元素在哪些区间中出现过,如果之前的元素的质因数和当前元素有相同的元素,那就不计入之前元素 存在的区间,如果有多个质因数,那就记录每个质因数的区间数量,最后得到区间的个数,就是这个元素的贡献度自己都 写糊涂了

    接下来以样例2再现一下这个过程:

    样例2中给了一个长度(n)为10的数组

    序号(i) 1 2 3 4 5 6 7 8 9 10
    元素(ai) 6 7 5 5 4 9 9 1 8 12
    质因数(x) 2 7 5 5 2 3 3 0 2 2
    3 3
    • **第一个元素的质因数 2 **,它能贡献的区间有[1,1], [1,2] ······[1,10] 共10个

      第一个元素的质因数3, 它能贡献的区间有[1,1], [1,2] ······[1,10] 共10个

      那么第一个元素的贡献为10 + 10 = 20

    • 第二个元素的质因数7 , 它能贡献的区间有[1,2],[1,3],……,[1,10] 和 [2,2],[2,3],……,[2,10] 共18个区间,那么第二个元素的贡献为9 + 9 = 18

    • 第三个元素的质因数5, 它所能贡献的区间[1, 3], [1, 4], ......, [1 10], [2, 3], [2, 4], ......., [2, 10], [3, 3], [3, 4], ......, [3, 10]共24个元素,那么第三个元素的贡献为8 + 8 + 8 = 24

      在第四个元素之前,前三个元素都是都没有重复的质因数,经过观察,我们不免能发现一个规律:**一个元素的质因数的贡献度 =(长度 + 1 - 当前元素的个数) * 序号 ** 即(n + 1 - i) * i

    • 但是,第四个元素出现了和第三个元素相同的质因数,如果按照之前的规律,那么这个这个元素的质因数的贡献度为 28,也就是说该元素包括了 [1,4], [1,5], ...., [1, 10], [2, 4], [2,5], .....[2, 10], [3, 4], ......, [3, 10] , [4, 4], [4, 5], ...... ,[4, 10] 。但是,只有[4, 4], [4, 5], ...... ,[4, 10]这8个区间是之前元素的质因数没有贡献的区间,所以第四个元素的贡献度是8

      所以,这个元素的贡献度 = (n + 1 - i) * i - (n + 1 - l) * l (l是上次质因数出现的位置), 化简之后得到了最终的关系式: (n + 1 - l) * (i - last)(last 是上一次质因数出现的位置) 。这样一来,就算是基本解决这个问题了。

      AC代码

      #include<iostream>
      using namespace std;
      const int N = 1e6 + 10000;
      long long q[N];   //注意数据范围,防爆
      long long last[N];
      int n;
      
      int main(){
          ios::sync_with_stdio(false), cin.tie(0);
          long long ans = 0;//储存答案
          cin >> n;
          for(int i = 1; i <= n; i++) cin >> q[i];
          for(int i = 1; i <= n; i++){
              long long x = q[i];
              for(int j = 2; j * j <= x; j++){
                  if(x % j != 0) continue;
                  while(x % j == 0) x /= j;//以上为求质因数
                  ans += (n + 1 - i) * (i - last[j]);//记录答案
                  last[j] = i;//储存质因数出现的位置
              }
              if(x != 1){ //处理最后的质因数
                  ans += (n + 1 - i) * (i - last[x]);
                  last[x] = i;
              }
          }
          cout << ans << endl;
      
          return 0;
      }
      

      这篇题解有些的地方阐述的不是很好,奈何本人表达能力有限,希望各位大佬能对这篇题解提出一些宝贵的建议,指出改进的地方

  • 相关阅读:
    何为OOM
    mysql 获取连接id与线程id
    oracle 字符集
    leetcode 542 01 Matrix, 01矩阵 JavaScript解法
    免费的API
    KNN算法
    linux_CentOS7安装MariaDB
    Django_模板标签
    celery_异步任务队列
    Django_设置和读取cookie
  • 原文地址:https://www.cnblogs.com/FrankOu/p/14236583.html
Copyright © 2020-2023  润新知