首页 > 其他分享 >CF1900D Small GCD

CF1900D Small GCD

时间:2023-12-12 23:34:52浏览次数:41  
标签:prime phi GCD int sum long Small include CF1900D

Link

这是一个需要欧拉反演的题目

首先,可以知道只和数字之间的大小有关,数列的顺序无关,那么就可以首先排一个序方便解决该问题。

根据欧拉函数的性质,知道\(n=\sum_{d|n}\phi{(n)}\)

那么我们每次先确定中间的数\(a_j\),然后根据公式,得他它得贡献是\(\sum_{i=1}^{j-1}gcd(a_{i},a_{j})\)

用欧拉函数处理一下这个东西后面的\(gcd\),然后得到\(\sum_{i=1}^{j-1}\sum_{d|a_{i}}\sum_{d|a_{j}}\phi{(d)}\)

交换一下求和的顺序,得到\(\sum_{d|a_{j}}\sum_{i=1}^{j-1}\sum_{d|a_{i}}\phi{(d)}\),显然的,后面就是这个因数\(d\)的出现次数

所以可以化简为\(\sum_{d|a_{j}}cnt_{d}*\phi{(d)}\)

这个东西就可以很快的求出来了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<bitset>
#define int long long
using namespace std;
int phi[100005];
int not_prime[100005];
int prime[100005];
int p;
int a[100001];
long long ans;
void Eul(){
	phi[1]=1;
	not_prime[1]=0;
	for(int i=2;i<=100000;++i){
		if(!not_prime[i]){
			prime[++p]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=p&&i*prime[j]<=100000;++j){
			not_prime[i*prime[j]]=1;	
			if(i%prime[j]==0){
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
		}
	}
}
int t;
int n;
int cnt[100005];
signed main(){
	Eul();
	scanf("%lld",&t);
	while(t--){
		memset(cnt,0,sizeof(cnt));
		scanf("%lld",&n);
		for(int i=1;i<=n;++i)
			scanf("%lld",&a[i]);
		sort(a+1,a+n+1);
		ans=0;
		for(int i=1;i<=n;++i){
			long long tem=0;
			for(int j=1;j*j<=a[i];j++){
				if(a[i]%j!=0) continue;
				tem+=phi[j]*cnt[j];
				cnt[j]++;
				if(j*j!=a[i]){
					tem+=phi[a[i]/j]*cnt[a[i]/j];
					cnt[a[i]/j]++;
				}
			}
			ans+=tem*(n-i);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

标签:prime,phi,GCD,int,sum,long,Small,include,CF1900D
From: https://www.cnblogs.com/For-Miku/p/17898116.html

相关文章

  • ARC169 B Subsegments with Small Sums 题解
    LinkARC169BSubsegmentswithSmallSumsQuestion\(x\)是一个序列,定义\(f(x)\)为把序列\(x\)切成几段,每段的和不能超过\(S\)的最小段数给出序列\(A=(A_1,A_2,\cdots,A_N)\)求:\[\sum_{1\lel\leN}f((A_l,A_{l+1},\cdots,A_r))\]Question先考虑一个结论,\(x\)为......
  • 无序对的$gcd$
    \(N\)为上确界,\(n\)为\(a\)数组元素个数,\(D\)为约数个数。方法一\(1.\)求出\(d\),\(d[i]\)表示\(i\)的所有约数(有序)。时间复杂度:\(O(NlogN)\)vector<int>d[N+1];for(inti=1;i<=N;i++)for(intj=i;j<=N;j+=i)d[j].pb(i);\(2.\)求出\(f......
  • [ABC254E] Small d and k 题解
    题目传送门一道暴力题。度数和\(k\)那么小?直接暴力\(n\)遍bfs,注意bfs的队列只能push距离不超过\(3\)的点。但有个问题,每次bfs都需要清空一次距离数组,这样子的时间复杂度是\(O(n^2)\)的。但也不难想到,距离数组中被赋值的地方不会很多,记录一下就行。Code#include......
  • CF1900D - Small GCD 题解
    1900D-SmallGCD给定序列\(A\),定义\(f(a,b,c)\)为\(a,b,c\)中最小的次小的数的\(\gcd\),求:\[\sum_{i=1}^n\sum_{j=i+1}^n\sum_{k=j+1}^nf(a_i,a_j,a_k)\]题解目前来说有两种方法,都十分有启发意义,但是有共同的开头。考虑到\(A\)的顺序实际上没有......
  • Make Lexicographically Smallest Array by Swapping Elements
    MakeLexicographicallySmallestArraybySwappingElementsYouaregivena 0-indexed arrayof positive integers nums anda positive integer limit.Inoneoperation,youcanchooseanytwoindices i and j andswap nums[i] and nums[j] if |nums......
  • Codeforces Round 911 (Div. 2) D. Small GCD
    题目链接:https://codeforces.com/contest/1900/problem/D对于已经排序好的数组\(a\),我们需要计算:\[\sum_{i=1}^n\sum_{j=i+1}^ngcd(a_i,a_j)*(n-j)\]由于\(\sum_{d|n}\phi(d)=n\),因此:\[\gcd(a_i,a_j)=\sum_{d|a_i,d|a_j}\psi(d)\]代入可得:\[\sum_{i=1}^n\su......
  • CF1900 D Small GCD 题解
    LinkCF1900DSmallGCDQuestion定义\(f(x,y,z)=\gcd(a,b)\),其中\(a,b\)为\(x,y,z\)中较小的那两个数给出数组\(a\),求\[\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n\sum\limits_{k=j+1}^nf(a_i,a_j,a_k)\]三个求和符号本质上就是选数组\(a\)中的三个数,也就是说,数......
  • D. Small GCD
    D.SmallGCDLet$a$,$b$,and$c$beintegers.Wedefinefunction$f(a,b,c)$asfollows:Orderthenumbers$a$,$b$,$c$insuchawaythat$a\leb\lec$.Thenreturn$\gcd(a,b)$,where$\gcd(a,b)$denotesthegreatestcommondivisor(GCD)ofi......
  • ORA-06502: PL/SQL: 数字或值错误:character string buffer too small
    原因是:DBMS_LOB.SUBSTR(CLOB)报错:超过缓存区长度解决办法:1、将自定义函数中的字符数参数设置为更大的数字(最大32767)。注意,这一设置和Oracle的版本有关系(Oracle10最大为4000,Oracle12可达32767)2、如果是拼接的字段来源是子表,那么就不在原sql中查对应字段,而是在后台JAVA中......
  • AtCoder Regular Contest 144 E GCD of Path Weights
    洛谷传送门AtCoder传送门喵喵题。考虑若所有点权都已确定,如何求\(1\)到\(n\)所有路径权值和的\(\gcd\)。考虑如何check一个\(x\)是否合法。\(x\)合法的充要条件是,把不能从\(1\)到达的点和不能到达\(n\)的点扔掉后,存在一组\(\{f_n\}\),使得对于每条\(u\tov\)......