P9920 题解

· · 题解

题目描述

给出一个函数 f(d),给出 g(n)=\sum\limits_{d|n}f(d) 其中 k\bmod 998244353 的值,对于每个测试点,有 t 组数据,对于每一组数据,给出 d,求 f(d)\bmod998244353 的值。

Sub0

基础结论,g(n)=[n=1]f(n)=\sum\limits_{d|n}μ(d)g(\tfrac{n}{d})=μ(n)

核心代码:

for(long long i=2;i*i<=n;i++)
{
    if(n%i==0)
    {
        n/=i;
        if(n%i==0)
        {
            ans=0;
        }
        else 
        {
            ans*=-1;
        }
    }
}
if(n>1)
{
    ans*=-1;
}

Sub1

一眼丁真,g(n)=d(n)f(n)=\sum\limits_{d|n}μ(d)d(\tfrac{n}{d})=1

核心代码:

cout<<1<<endl;

Sub2

核心代码: ```cpp cout<<0<<endl; ``` ### Sub3 最抽象的一集,发现 $g(p^k)$ 是一个随机数,反演可得 $f(n)=g(n)=\sum\limits_{d\neq n,d|n}f(d)$。 核心代码: ```cpp for(long long i=1;i<=P;i++) { f[i]=y[i];//y为g(d) } for(long long i=1;i<=100000;i++) { for(long long j=i+i;j<=100000;j+=i) { f[j]=(f[j]-f[i]+mod)%mod; } } ``` ### Sub4 有些难度,反演两次后,设这个奇怪的反演函数为 $j$,发现是一个平方数,即 $j(p)=(p-1)^2$,得 $j(n)=\prod(j(p^k))=\prod(p^{k-1}(p-1))^2=\varphi^2(n)$,所以 $f(n)=\sum\limits\limits_{d|n}j(d)=\sum\limits_{d|n}\varphi^2(d)$。 核心代码: ```cpp for(long long i=1;i*i<=n;i++) { long long res; if(n%i==0) { res=phi(i);//phi部分自写 ans=(ans+1ll*res*res)%mod; res=phi(n/i); ans=(ans+1ll*res*res)%mod; } if(i*i==n) { res=phi(i); ans=(ans-1ll*res*res)%mod; } } ``` ### Sub5 简单一次反演后,得 $f(p^k)=p^{2k-1}$,套下数据发现大质数相乘,输出 $n$。 核心代码: ```cpp cout<<n<<endl; ``` ### Sub6 最困难的一集,我们已知 $g(n)=n^2$,则 $f(p^k)=\sum\limits_{d|p^k}d^2μ(\tfrac{p^k}{d})$,因为 $p^0,p^1,p^2$ 等整除 $p^k$,且根据 $μ$ 的定义,可知只有为 $k-1,k$ 时对总答案有贡献,所以 $f(p^k)=p^{2k}-p^{2k-2}=p^{2k}(1-\tfrac{1}{p^2})$,得 $f(n)=\prod p^{2k}(1-\tfrac{1}{p^2})=n^2\prod (1-\tfrac{1}{p^2})$。 核心代码: ```cpp long long mill[20]={0,2,325,9375,28178,450775,9780504,1795365022}; bool miller(long long n) { if(n<3) { return (n==2); } long long u=n-1,t=0; while(u%2==0) { u>>=1,t++; } for(long long i=1;i<=7;i++) { if(mill[i]>n) { continue; } long long a=mill[i],v=pow(a,u,n),j; if(v==1) { continue; } j=1; for(;j<=t;j++) { if(v==n-1) { break; } v=(__int128)v*v%n; } if(j==t+1) { return 0; } } return 1; } long long f2(long long x,long long c,long long n) { return ((__int128)x*x+c)%n;//个人习惯 } long long pollard(long long n) { if(n==4) { return 2; } while(1) { long long c=rnd()%(n-1)+1,t=0,r=0,p=1,q,d; do { for(long long i=0;i<128;i++) { t=f2(t,c,n); r=f2(f2(r,c,n),c,n); if(t==r) { break; } q=(__int128)p*abs(t-r)%n; if(q==0) { break; } p=q; } d=__gcd(p,n); if(d>1) { return d; } }while(t!=r); } } long long get(long long n) { if(mp[n]) { return mp[n]; } if(miller(n)) { return mp[n]=n; } long long k=pollard(n); return mp[n]=((k==n)?n:mp[n]=max(get(k),get(n/k))); } void ans7() { while(T--) { long long n; cin>>n; __int128 ans=(__int128)n*n; while(n>1) { long long p=get(n); ans=ans/((__int128)p*p)*((__int128)p*p-1); while(n%p==0) { n/=p; } } cout<<(long long)(ans%mod)<<endl; } } ``` Pollard-rho 算法求质因数请转场 [P4718](https://www.luogu.com.cn/problem/P4718)。 ### Sub7 看看数据,动了亿点脑子,得 $f(p^k)=ap^{3k}+bp^{2k}+cp^k+d$,运用拉格朗日插值,脑量不足,只得 $a=114$,运用人类智慧,得 $a=114,b=514,c=1919,d=810$。 核心代码: ```cpp for(long long i=2;i*i<=n;i++) { if(n%i==0) { long long k=1; while(n%i==0) { n/=i,k*=i; } if(k>1) { po=114; po=(po*k+514)%mod; po=(po*k+1919)%mod; po=(po*k+810)%mod; ans=ans*po%mod; } } } if(n>1) { po=114; po=(po*n+514)%mod; po=(po*n+1919)%mod; po=(po*n+810)%mod; ans=ans*po%mod; } ``` ### Sub8 看数据发的,猜测 $f(n)=n^2\bmod3$,正确! 核心代码: ```cpp cout<<1ll*n*n%3<<endl; ``` 总结,非常好莫比乌斯反演,下次别出了。