潜龙未见静水流,沉默深藏待时秋。一朝破空声势振,惊世骇俗展雄猷。
随笔 - 80, 文章 - 0, 评论 - 3, 阅读 - 2132

P4240 毒瘤之神的考验 题解

目录

题目描述

T 组询问,给定 n,m ,求 (i=1nj=1mφ(ij))mod998244353

数据范围

  • 1T104,1n,m105

时间限制 2s ,空间限制 512MB

分析

首先有一个经典结论:

φ(ij)=φ(i)φ(j)gcd(i,j)φ(gcd(i,j))

证明:

vp(i)=α,vp(j)=0 ,则 p 在两边的贡献均为 pα1(p1)

vp(i)=α,vp(j)=β ,则 p 在左边的贡献为 pα+β1(p1) ,右边的贡献为 pα1(p1)pβ1(p1)pp1=pα+β1(p1)

其实证明很 naive ,真正有用的是把这个式子积累下来,如果忘了也可以通过比较 φ(i)φ(j)φ(ij) 的差距现推。

接下来是常规操作。

i=1nj=1mφ(i)φ(j)gcd(i,j)φ(gcd(i,j))=d=1dφ(d)i=1nj=1m[gcd(i,j)=d]φ(i)φ(j)=d=1dφ(d)i=1n/dj=1m/d[gcd(i,j)=1]φ(id)φ(jd)=d=1dφ(d)i=1n/dj=1m/dxgcd(i,j)μ(x)φ(id)φ(jd)=d=1dφ(d)x=1μ(x)i=1n/dxφ(idx)j=1n/dxφ(jdx)=t=1dtdφ(d)μ(td)i=1n/tφ(it)j=1m/tφ(jt)

f(t)=dtdφ(d)μ(td),g(t,n)=i=1nφ(it) ,则 f 可以 O(nlogn) 预处理, g 的状态数为调和级数,同样可以 O(nlogn) 预处理。

原式化为:

t=1f(t)g(t,nt)g(t,mt)

虽然看到了 nt,mt ,但是不能整除分块。这是因为 g 内部仍然和 t 有关。

w=105 ,考虑根号分治

  • 如果 tnB ,暴力枚举 t 即可,时间复杂度 O(wB)
  • 如果 t>nB ,则 ntB 。对 1mnB ,预处理 s(n,m,k)=t=1kf(t)g(t,n)g(t,m) ,整除分块可以做到 O(B) 回答。

由于 g 要求 knw ,因此 s 的状态数为 n=1Bm=1nwn=wB ,可以接受。

时间复杂度 O(wB+T(B+wB)) ,取 B=w ,时空复杂度均为 O(ww)

#include<bits/stdc++.h>
using namespace std;
const int B=200,maxn=1e5+5,mod=998244353;
int m,n,t,res;
int p[maxn],mu[maxn],phi[maxn];
int f[maxn];
vector<int> g[maxn],s[B+5][B+5];
bitset<maxn> b;
int qpow(int a,int k)
{
    int res=1;
    for(;k;a=1ll*a*a%mod,k>>=1) if(k&1) res=1ll*res*a%mod;
    return res;
}
void init(int n)
{
    mu[1]=phi[1]=1;
    for(int i=2,cnt=0;i<=n;i++)
    {
        if(!b[i]) p[++cnt]=i,mu[i]=-1,phi[i]=i-1;
        for(int j=1;j<=cnt&&i*p[j]<=n;j++)
        {
            b[i*p[j]]=1;
            if(i%p[j]==0)
            {
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }
            mu[i*p[j]]=-mu[i],phi[i*p[j]]=phi[i]*(p[j]-1);
        }
    }
    for(int i=1;i<=n;i++)
    {
        g[i].resize(n/i+5);
        for(int j=1,inv=qpow(phi[i],mod-2);i*j<=n;j++)
        {
            f[i*j]=(f[i*j]+1ll*i*inv*mu[j])%mod;
            g[i][j]=(g[i][j-1]+phi[i*j])%mod;
        }
    }
    for(int i=1;i<=B;i++)
        for(int j=1;j<=i;j++)
        {
            s[i][j].resize(n/i+5);
            for(int k=1;k<=n/i;k++)
                s[i][j][k]=(s[i][j][k-1]+1ll*f[k]*g[k][i]%mod*g[k][j])%mod;
        }
}
int main()
{
    scanf("%d",&t),init(maxn-5);
    while(t--)
    {
        scanf("%d%d",&n,&m),res=0;
        if(n<m) swap(n,m);
        for(int i=1;i<=min(n/B,m);i++) res=(res+1ll*f[i]*g[i][n/i]%mod*g[i][m/i])%mod;
        for(int l=n/B+1,r=0;l<=m;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            res=(0ll+res+s[n/l][m/l][r]-s[n/l][m/l][l-1])%mod;
        }
        printf("%lld\n",(res+mod)%mod);
    }
    return 0;
}

posted on   peiwenjun  阅读(5)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示