AT_agc038_c LCMs 题解

  • 给定一个长度为 N 的数列 A1,A2,A3,,AN
  • 请你求出 i=1Nj=i+1Nlcm(Ai,Aj) 的值模 998244353 的结果。
  • 1N2×1051Ai106

M=AMax

首先,第二个 的下标不从 1 让我们的推演举步维艰。因为 lcm 是对称的,所以我们可以算两个完整的 ,再减去对角线、除以 2 得到答案。即:

i=1Nj=i+1Nlcm(Ai,Aj)=i=1Nj=1Nlcm(Ai,Aj)i=1Nlcm(Ai,Ai)2=i=1Nj=1Nlcm(Ai,Aj)i=1NAi2

发现 i=1Nlcm(Ai,Ai) 就是 A 数组的和。输入的时候记录一下即可。

i=1Nj=1Nlcm(Ai,Aj)=i=1Nj=1NAiAjgcd(Ai,Aj)=gMi=1Nj=1NAiAjg[gcd(Ai,Aj)=g]=gM1gi=1Nj=1NAiAj[gcd(Ai,Aj)=g][g|Ai][g|Aj]=gM1gi=1Nj=1NAiAj[gcd(Aig,Ajg)=1][g|Ai][g|Aj]=gM1gi=1Nj=1NAiAj[g|Ai][g|Aj][gcd(Aig,Ajg)=1]=gM1gi=1Nj=1NAiAj[g|Ai][g|Aj]d|gcd(Aig,Ajg)μ(d)=gMdMgμ(d)gi=1Nj=1NAiAj[g|Ai][g|Aj][d|gcd(Aig,Ajg)]=gMdMgμ(d)gi=1Nj=1NAiAj[g|Ai][g|Aj][d|Ai][d|Aj]=gMdMgμ(d)gi=1Nj=1NAiAj[gd|Ai][gd|Aj]=gMdMgμ(d)gi=1N[gd|Ai]Aij=1NAj[gd|Aj]=gMdMgμ(d)g(i=1N[gd|Ai]Ai)2=gMdMgμ(d)g(i=1N[gd|Ai]Ai)2

ci 表示输入的 A 数组中含有 cii,则显然下式成立:

i=1N[gd|Ai]Ai=gd|iMi×ci

所以原式:

Ans=gMdMgμ(d)g(i=1N[gd|Ai]Ai)2=gMdMgμ(d)g(gd|iMi×ci)2

设函数 f(x)=x|iMi×ci,则原式:

Ans=gMdMgμ(d)g(gd|iMi×ci)2=gMdMgμ(d)gf2(gd)

f 可以在 O(nlnn) 的复杂度内预处理出来,剩下的又是个 O(nlnn) 的暴力,直接计算即可。
注意到有除法操作,需要线性求逆元。线性求逆元公式:

invi=(pi×invpmodi)modp


代码:

// Problem: AT_agc038_c [AGC038C] LCMs
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/AT_agc038_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#include <bits/extc++.h>
#define INF 0x7fffffff
#define MAXN 1000005
#define eps 1e-9
#define foru(a,b,c)	for(int a=b;a<=c;a++)
#define RT return 0;
#define db(x)	cout<<endl<<x<<endl;
#define LL long long
#define int LL
#define LXF int
#define RIN rin()
#define HH printf("\n")
using namespace std;
inline LXF rin(){
	LXF x=0,w=1;
	char ch=0;
	while(ch<'0'||ch>'9'){ 
	if(ch=='-') w=-1;
	ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
	x=x*10+(ch-'0');
	ch=getchar();
	}
	return x*w;
}
const int p=998244353;
int n,M;
bitset<MAXN> vis;
int c[MAXN];
int f[MAXN],mu[MAXN],inv[MAXN];
vector<int> prim;
void pre(){
	vis[1]=mu[1]=1;
	inv[1]=1;
	for(int i=2;i<=MAXN-5;i++){
		inv[i]=(p-p/i)*inv[p%i]%p;
		if(!vis[i]){
			prim.emplace_back(i);
			mu[i]=-1;
		}
		for(int j=0;j<prim.size()&&i*prim[j]<=MAXN-5;j++){
			vis[i*prim[j]]=1;
			if(i%prim[j]==0)	break;
			mu[i*prim[j]]=-mu[i];
		}
	}
}
signed main(){
	n=RIN;
	pre();
	int x;
	int tot=0;
	for(int i=1;i<=n;i++){
		x=RIN;
		tot+=x;
		tot%=p;
		c[x]++;
		M=max(M,x);
	}
	n=M;
	for(int x=1;x<=n;x++){
		for(int i=x;i<=n;i+=x){
			f[x]+=i*c[i]%p;
			f[x]%=p;
		}
	}
	int ans=0;
	for(int g=1;g<=n;g++){
		for(int d=1;d*g<=n;d++){
			ans+=f[g*d]%p*f[g*d]%p*mu[d]%p*inv[g]%p;
			ans%=p;
		}
	}
	ans-=tot;
	ans=(ans%p+p)%p;
	ans=ans*inv[2]%p;
	printf("%lld",ans);
	return 0;
}
posted @   Cap1taL  阅读(31)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示