首页 > 其他分享 >Codeforces Round 911 (Div. 2) D

Codeforces Round 911 (Div. 2) D

时间:2023-11-27 22:11:24浏览次数:42  
标签:cnt right limits int 元素 Codeforces phi Div 911

D. Small GCD

题意

给定数组 \(a\) ,求出数组 \(a\) 中所有三元组中较小的两个元素的 \(gcd\) 的和.

分析

显然数组中元素的顺序不影响统计答案,为了方便先将数组排个序;
枚举中间的元素 \(a_j\) ,那么只有它前边的元素能与其产生贡献,它后边的元素个数就是这个贡献的倍数,下面考虑枚举中间元素时的贡献
所求即为 \(\sum\limits_{i=1}^{j-1}{gcd\left(a_i,a_j\right)}\) , 无论怎样的暴力都是 \(n^2\) 的。
赛时没想出来优化,赛后看了别人代码才想到欧拉反演。

欧拉反演公式:\(n = \sum\limits_{d\mid n}{\phi \left(n\right)}\)
证明欧拉反演的话只要证明因子的的欧拉函数之和是一个积性函数就能顺利整出来。

有了上述结论,原式子可以转为 \(\sum\limits_{i=1}^{j-1}\sum\limits_{d\mid\left(a_i,a_j\right)}{\phi \left(d\right)}\)
已经是一个易处理的柿子,考虑实现细节
从前往后枚举元素,假设已经处理到了 \(a_j\) ,枚举因子 \(x\) ,如果前面 \(j - 1\) 个元素中已经出现了 \(cnt\) 次因子 \(x\) ,那么这一位的贡献直接加上 \(cnt * \phi(x)\), 同时++cnt;
最后给每一位贡献乘上系数即可。

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL),cout.tie(NULL)
const int N = 1e5 + 7;
int phi[N];
void init(int n){
    for (int i(1); i <= n; ++i) phi[i] = i;
    for (int i(1); i <= n; ++i)
        for (int j(2 * i); j <= n; j += i)
            phi[j] -= phi[i];
}

void doit(){
    int n; cin >> n;
    vector<int> a(n + 1), cnt(N);
    for (int i(1); i <= n; ++i) cin >> a[i];
    sort(a.begin() + 1, a.end());

    ll ans = 0;

    for (int i(1); i <= n; ++i){
        int x = a[i];
        ll res = 0;
        for (int j(1); j * j <= x; ++j){
            if (x % j) continue;
            res += 1ll * phi[j] * cnt[j]++;
            if (j * j != x) res += 1ll * phi[x / j] * cnt[x / j]++;
        }
        ans += res * (n - i);
    }

    cout << ans << '\n';

}

int main(){
    IOS;
    //freopen("in.txt", "r", stdin);
    int T = 1; cin >> T;
    init(N);
    while (T--){
        doit();
    }
    return 0;
}

标签:cnt,right,limits,int,元素,Codeforces,phi,Div,911
From: https://www.cnblogs.com/ancer/p/17860514.html

相关文章

  • Codeforces Round 911 (Div. 2)
    CodeforcesRound911(Div.2)A-CoverinWater解题思路:如果存在三个以上相邻的格子需要填,那么答案为二,否则有多少空格答案为多少。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;typedefpair<int,int>pii;#definefifirst#definese......
  • Codeforces Round 911 (Div. 2) A-C
    CodeforcesRound911(Div.2)A.CoverinWater题意:有n个单元格,有的空着有的被堵住,可以做两种操作:给一个空着的单元格放入水;将单元格的水移到另一个单元格。并且,若一个单元格左右两边都有水,它也会自动充满水。所有空着的单元格都要充满水,求最少的放入水的次数思路:若存在三......
  • CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!)
    20231127A.JaggedSwaps题意是:给你一个数组进行无数次的操作问你能不能单调思路:通过观察发现进行操作大的一定会被放在后面,所以一定会单调,但是操作是从2开始的,所以下表1的地方一定要是1usingnamespacestd;inta[20];voidsolve(){intn;cin>>n;for(in......
  • Codeforces Round 911 (Div. 2)
    A-CoverinWater三个连续的.就可以造出无限水,这时直接输出\(2\),否则输出区间长度和。SubmissionB-LauraandOperations每次操作不会改变不需要的两个数的个数的和的奇偶性,而当这个和为偶数的时候,通过若干操作一定可以全部变成另一个。SubmissionC-Anji'sBinary......
  • 汇编div的注意
    无符号除法32位模式下,DIV(无符号除法)指令执行8位、16位和32位无符号数除法,结果以余数和商的方式表现。格式如下:DIV8位寄存器或内存DIV16位寄存器或内存DIV32位寄存器或内存被除数除数商余数AXreg/mem8ALAHDX:AXreg/mem16AXDXEDX:EAXreg/mem32EAXEDX根据以上表格可......
  • Codeforces Round 911 (Div. 2) A
    真的太菜了……题目链接:Problem-A-Codeforces//Problem:A.CoverinWater//Contest:Codeforces-CodeforcesRound911(Div.2)//URL:https://codeforces.com/contest/1900/problem/0#//MemoryLimit:256MB//TimeLimit:1000ms////PoweredbyCPEd......
  • [Codeforces] CF1799B Equalize by Divide
    序列操作(divide.cpp)—CF1799B—1200题目描述给您一个\(a_1,a_2,\dotsa_n\)这样的正整数数组,您可以对它进行多次(可以是零次)这样的操作:选择两个索引\(i,j(1\leqi,j\leqn,i\neqj)\);将\(a_i\)赋值为\(\lceil\frac{a_i}{a_j}\rceil\)。这里的\(\lceilx\rceil\)......
  • [Codeforces] CF1747C Swap Game
    游戏(game.cpp)—CF1747C—1200\(时间:1s\space|\space空间:250MB\)题面翻译Alice和Bob两个人在玩游戏。有一个长度为\(n\)的序列\(a\),Alice和Bob两人轮流完成一个操作,Alice先开始。每个人可以将数列的第一个数减\(1\),并将它与后面序列的一个数进行交换,如果一个......
  • CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!)
    CodeTONRound7(Div.1+Div.2,Rated,Prizes!)A-JaggedSwaps解题思路:若\(a[1]=1\),则可以。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;typedefpair<int,int>pii;#definefifirst#definesesecondvoidsolve(){......
  • CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!)
    CodeTONRound7(Div.1+Div.2,Rated,Prizes!)A-JaggedSwapsintmain(){IOS;for(cin>>_;_;--_){cin>>n;rep(i,1,n)cin>>a[i];while(true){boolf=0;rep(i,......