2023“钉耙编程”中国大学生算法设计超级联赛(4)Guess

题目大意

S n = ∑ d ∣ n μ ( n d ) ln ⁡ ( d ) S_n=\sum\limits_{d\mid n}\mu(\frac nd)\ln(d) Sn=dnμ(dn)ln(d)

e S n   m o d   998244353 e^{S_n}\bmod 998244353 eSnmod998244353

题解

变换式子
e S n = e ∑ d ∣ n μ ( n d ) ln ⁡ ( d ) = ∏ d ∣ n d μ ( n d ) = ∏ d ∣ n ( n d ) μ ( d ) \begin{aligned} e^{S_n}&=e^{\sum\limits_{d\mid n}\mu(\frac nd)\ln(d)}\\ &=\prod\limits_{d\mid n}d^{\mu(\frac nd)}\\ &=\prod\limits_{d\mid n}(\frac nd)^{\mu(d)} \end{aligned} eSn=ednμ(dn)ln(d)=dndμ(dn)=dn(dn)μ(d)

μ ( d ) \mu(d) μ(d) 的值进行研究

  • μ ( d ) = 0 \mu(d)=0 μ(d)=0,这时 ( n d ) μ ( d ) = 1 (\frac nd)^{\mu(d)}=1 (dn)μ(d)=1,对答案没有影响。
  • μ ( d ) = 1 \mu(d)=1 μ(d)=1,,这时 ( n d ) μ ( d ) = n d (\frac nd)^{\mu(d)}=\frac nd (dn)μ(d)=dn
  • μ ( d ) = − 1 \mu(d)=-1 μ(d)=1,,这时 ( n d ) μ ( d ) = d n (\frac nd)^{\mu(d)}=\frac dn (dn)μ(d)=nd

只有当 d = p 1 p 2 … p m d=p_1p_2\dots p_{m} d=p1p2pm,或者 d = 1 d=1 d=1 μ ( d ) \mu(d) μ(d) 才不等于 0 0 0,进一步说, μ ( d ) = ( − 1 ) m \mu(d)=(-1)^m μ(d)=(1)m

n n n 分解质因数得 n = p 1 c 1 p 2 c 2 … p m c m n=p_1^{c_1}p_2^{c_2}\dots p_{m}^{c_m} n=p1c1p2c2pmcm,记 A = p 1 p 2 … p m A=p_1p_2\dots p_m A=p1p2pm

于是枚举 d d d 变成了任意枚举 A A A 中的质数。使用 Pollard rho \text{Pollard rho} Pollard rho 算法可在 O ( n 4 ) O(\sqrt[4]{n}) O(4n ) 的时间可以分解 n n n,任意枚举 A A A 的质数的时间复杂度为 O ( 2 ω ( n ) ) O(2^{\omega(n)}) O(2ω(n)),单次时间复杂度是 O ( n 4 + 2 ω ( n ) ) O(\sqrt[4]{n}+2^{\omega(n)}) O(4n +2ω(n)),可以通过???赛时我一开始思路是这样,但是打挂了。赛后发现当有一个 p = 998244353 p=998244353 p=998244353 时,逆元求不了。后面 tanjunming2020 给我新思路。下面介绍这个新思路。

继续推上面的的式子

∏ d ∣ n ( n d ) μ ( d ) = n ∑ d ∣ n μ ( d ) ∏ d ∣ n d μ ( d ) = 1 ∏ d ∣ n d μ ( d ) = 1 ∏ d ∣ A d μ ( d ) \begin{aligned} \prod\limits_{d\mid n}(\frac nd)^{\mu(d)}&=\dfrac{n^{\sum\limits_{d\mid n}\mu(d)}}{\prod\limits_{d\mid n}d^{\mu(d)}}\\ &=\dfrac{1}{\prod\limits_{d\mid n}d^{\mu(d)}}\\ &=\dfrac{1}{\prod\limits_{d\mid A}d^{\mu(d)}}\\ \end{aligned} dn(dn)μ(d)=dndμ(d)ndnμ(d)=dndμ(d)1=dAdμ(d)1

观察 A A A 中的一个质数 p p p 对分母产生的贡献,固定选 p p p,枚举再选 i i i 个质数,然后在剩下的 m − 1 m-1 m1 个质数中选 i i i 个,莫比乌斯函数值为 ( − 1 ) i + 1 (-1)^{i+1} (1)i+1。所以分母为 ∏ p ∣ A p ∑ i = 0 m − 1 C m − 1 i ( − 1 ) i + 1 \prod\limits_{p\mid A}p^{\sum\limits_{i=0}^{m-1}C_{m-1}^i(-1)^{i+1}} pApi=0m1Cm1i(1)i+1

答案为 ∏ p ∣ A p ∑ i = 0 m − 1 C m − 1 i ( − 1 ) i \prod\limits_{p\mid A}p^{\sum\limits_{i=0}^{m-1}C_{m-1}^i(-1)^i} pApi=0m1Cm1i(1)i。(消掉了一个 − 1 -1 1 次方)

对组合数进行探究。分类讨论

  • m = 1 m=1 m=1,答案为 p p p
  • m m m 为偶数且大于 0 0 0,显然, C m − 1 i C_{m-1}^i Cm1i C m − 1 m − 1 − i C_{m-1}^{m-1-i} Cm1m1i,符号不同,大小相同,会全部消掉。答案为 0 0 0
  • m m m 为奇数且大于 1 1 1,由于 C n m = C n − 1 m + C n − 1 m − 1 C_n^m=C_{n-1}^m+C_{n-1}^{m-1} Cnm=Cn1m+Cn1m1,则
    ∑ i = 0 m − 1 C m − 1 i ( − 1 ) i = 2 + ∑ i = 1 m − 2 C m − 1 i ( − 1 ) i = 2 + ∑ i = 1 m − 2 C m − 2 i ( − 1 ) i + ∑ i = 1 m − 2 C m − 2 i − 1 ( − 1 ) i = 1 + ∑ i = 0 m − 2 C m − 2 i ( − 1 ) i + ∑ i = 0 m − 3 C m − 2 i ( − 1 ) i + 1 = ∑ i = 0 m − 2 C m − 2 i ( − 1 ) i + ∑ i = 0 m − 2 C m − 2 i ( − 1 ) i + 1 = 0 \begin{aligned} \sum\limits_{i=0}^{m-1}C_{m-1}^i(-1)^i&=2+\sum\limits_{i=1}^{m-2}C_{m-1}^i(-1)^i\\ &=2+\sum\limits_{i=1}^{m-2}C_{m-2}^i(-1)^i+\sum\limits_{i=1}^{m-2}C_{m-2}^{i-1}(-1)^i\\ &=1+\sum\limits_{i=0}^{m-2}C_{m-2}^i(-1)^i+\sum\limits_{i=0}^{m-3}C_{m-2}^{i}(-1)^{i+1}\\ &=\sum\limits_{i=0}^{m-2}C_{m-2}^i(-1)^i+\sum\limits_{i=0}^{m-2}C_{m-2}^{i}(-1)^{i+1}\\ &=0\\ \end{aligned} i=0m1Cm1i(1)i=2+i=1m2Cm1i(1)i=2+i=1m2Cm2i(1)i+i=1m2Cm2i1(1)i=1+i=0m2Cm2i(1)i+i=0m3Cm2i(1)i+1=i=0m2Cm2i(1)i+i=0m2Cm2i(1)i+1=0

全部情况考虑,得到结论:若 n = p k n=p^k n=pk,则答案为 p p p,否则答案为 1 1 1

这样,使用 Pollard rho \text{Pollard rho} Pollard rho 得到 n n n 最大的质因数,看它是否完全构成 n n n

代码如下

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 Int;
ll ksc(ll a,ll b,ll c)
{
    ll ans=0;
    while(b){
        if(b&1)
            ans=(ans+a)%c;
        a=(a+a)%c;
        b>>=1;
    }
    return ans;
}
ll ksm(ll a,ll b,ll c)
{
    ll ans=1;
    while(b){
        if(b&1)
            ans=(Int)ans*a%c;
        a=(Int)a*a%c;
        b>>=1;
    }
    return ans;
}
ll test[12]={2,3,5,7,11,13,17,19,23,29,31,37},maxn;
bool check(ll a,ll n)
{
    ll d=n-1,get=ksm(a,d,n);
    if(get!=1) return 1;
    while((d&1)^1)
        if(d>>=1,(get=ksm(a,d,n))==n-1) return 0;
        else if(get!=1) return 1;
    return 0;
}
bool miller_rabbin(ll n)
{
    if(n<40){
        for(int i=0;i<12;i++) if(test[i]==n) return 1;
        return 0;
    }
    for(int i=0;i<12;i++) if(check(test[i],n)) return 0;
    return 1;
}
ll gcd(ll a,ll b)
{
    return !b?a:gcd(b,a%b);
}
inline ll f(ll x,ll c,ll n)
{
    return ((Int)x*x+c)%n;
}
ll pollard_rho(ll x)
{
    ll s=0,t=0,c=1ll*rand()%(x-1)+1,val=1;
    for(int i=1;;i<<=1,s=t,val=1){
        for(int j=1;j<=i;j++){
            t=f(t,c,x);
            val=(Int)val*abs(t-s)%x;
            if(!(j%127)){
                ll d=gcd(val,x);
                if(d>1) return d;
            }
        }
        ll d=gcd(val,x);
        if(d>1) return d;
    }
}
vector<ll> aa,bb;
const ll mod=998244353;
ll Ans,invn,n;
void fac(ll x)
{
    if(x<=maxn||x<2) return;
    if(miller_rabbin(x)){
        maxn=max(maxn,x);
        return;
    }
    ll p=x;
    while(p>=x) p=pollard_rho(x);
    while(x%p==0) x/=p;
    fac(x),fac(p);
}
void dfs(int k,ll x,int num,ll y)
{
    if(k>=aa.size()){
        if(num&1) Ans=Ans*x%mod*invn%mod;
        else Ans=Ans*(n%mod)%mod*y%mod;
        return;
    }
    dfs(k+1,x,num,y);
    dfs(k+1,x*aa[k]%mod,num+1,y*bb[k]%mod);
}
int main()
{
    srand((unsigned)time(NULL));
    ll t;
    scanf("%lld",&t);
    while(t--){
        maxn=0;
        scanf("%lld",&n);
        if(n==1){printf("1 ");continue;}
        fac(n);
        while(n%maxn==0) n/=maxn;
        if(n==1) printf("%lld ",maxn%mod);
        else printf("1 ");
    }
}
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值