ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

The 2019 ACM-ICPC China Shannxi Provincial Programming Contest B. Product(杜教筛+约数)

2019-06-08 17:49:09  阅读:245  来源: 互联网

标签:约数 Provincial Product right frac gcd sum nd lfloor


题意

给你n(n109)n(n\leq 10^9)n(n≤109),m(m2×109)m(m\leq 2\times10^9)m(m≤2×109),p(p2×109)p(p\leq 2\times10^9 )p(p≤2×109),ppp为质数求
i=1nj=1nk=1nmgcd(i,j)[kgcd(i,j)]\prod_{i=1}^n\prod_{j=1}^n\prod_{k=1}^nm^{gcd(i,j)[k|gcd(i,j)]}i=1∏n​j=1∏n​k=1∏n​mgcd(i,j)[k∣gcd(i,j)]
ppp的答案

思路

我们先只考虑指数部分和欧拉降幂那么有
i=1nj=1nk=1ngcd(i,j)[kgcd(i,j)] mod p1\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^ngcd(i,j)[k|gcd(i,j)]\ mod\ p-1i=1∑n​j=1∑n​k=1∑n​gcd(i,j)[k∣gcd(i,j)] mod p−1
可以认为k=1ngcd(i,j)[kgcd(i,j)]\sum_{k=1}^ngcd(i,j)[k|gcd(i,j)]k=1∑n​gcd(i,j)[k∣gcd(i,j)]
计算的是gcd(i,j)gcd(i,j)gcd(i,j)*gcd(i,j)的约数个数gcd(i,j)∗gcd(i,j)的约数个数,我们用σ(d)\sigma (d)σ(d)表示ddd的约数个数
那么原式就等于
i=1nj=1ngcd(i,j)σ(gcd(i,j))\sum_{i=1}^n\sum_{j=1}^ngcd(i,j)\sigma(gcd(i,j))i=1∑n​j=1∑n​gcd(i,j)σ(gcd(i,j))
d=gcd(i,j)d=gcd(i,j)d=gcd(i,j)得
d=1ndσ(d)i=1nj=1n[gcd(i,j)==d]\sum_{d=1}^nd\sigma(d)\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)==d]d=1∑n​dσ(d)i=1∑n​j=1∑n​[gcd(i,j)==d]

d=1ndσ(d)i=1ndj=1nd[gcd(i,j)==1]\sum_{d=1}^nd\sigma(d)\sum_{i=1}^{\left \lfloor\frac{n}{d}\right \rfloor}\sum_{j=1}^{\left \lfloor\frac{n}{d}\right \rfloor}[gcd(i,j)==1]d=1∑n​dσ(d)i=1∑⌊dn​⌋​j=1∑⌊dn​⌋​[gcd(i,j)==1]
考虑后面的部分
i=1ndj=1nd[gcd(i,j)==1]\sum_{i=1}^{\left \lfloor\frac{n}{d}\right \rfloor}\sum_{j=1}^{\left \lfloor\frac{n}{d}\right \rfloor}[gcd(i,j)==1]i=1∑⌊dn​⌋​j=1∑⌊dn​⌋​[gcd(i,j)==1]
可以用莫比乌斯反演做但是这恰好iii和jjj的上限都nnn,可以认为是1n1-n1−n中互质的数对数,考虑每个iii的贡献其实就是φ(i)\varphi(i)φ(i)欧拉函数的值,那么答案就是欧拉函数的前缀和,但是由于iii,jjj的顺序是有影响的然后(1,1)(1,1)(1,1)只计算一次所以有
i=1ndj=1nd[gcd(i,j)==1]=2Φ(nd)1\sum_{i=1}^{\left \lfloor\frac{n}{d}\right \rfloor}\sum_{j=1}^{\left \lfloor\frac{n}{d}\right \rfloor}[gcd(i,j)==1]=2*\Phi(\left \lfloor\frac{n}{d}\right \rfloor)-1i=1∑⌊dn​⌋​j=1∑⌊dn​⌋​[gcd(i,j)==1]=2∗Φ(⌊dn​⌋)−1
其中φ\varphiφ为欧拉函数的和函数
那么原式就转化为
=d=1ndσ(d)(2Φ(nd)1)=\sum_{d=1}^nd\sigma(d)(2*\Phi(\left \lfloor\frac{n}{d}\right \rfloor)-1)=d=1∑n​dσ(d)(2∗Φ(⌊dn​⌋)−1)
然后我们再考虑一下
i=1niσ(i)\sum_{i=1}^ni\sigma(i)i=1∑n​iσ(i)
这个求和
可以把约数函数展开来
=i=1nidi1=\sum_{i=1}^ni\sum_{d|i}1=i=1∑n​id∣i∑​1
那么表示的就是对于每一个iii枚举他的因子有哪些,已知在1n1-n1−n中枚举iii的因子和枚举iii的倍数是等价的那么就有
=d=1ndii=\sum_{d=1}^n\sum_{d|i}i=d=1∑n​d∣i∑​i
iii为ddd的倍数,我们再把后面的展开来
=d=1n(d+2d+3d++ndd)=\sum_{d=1}^n(d+2d+3d+\cdots+\left \lfloor\frac{n}{d}\right \rfloor d)=d=1∑n​(d+2d+3d+⋯+⌊dn​⌋d)
后面就是一个等差数列
=d=1ndnd(nd+1)2=\sum_{d=1}^nd\frac{\left \lfloor\frac{n}{d}\right \rfloor(\left \lfloor\frac{n}{d}\right \rfloor+1)}{2}=d=1∑n​d2⌊dn​⌋(⌊dn​⌋+1)​
Id(n)=i=1niσ(i)Id(n)=\sum_{i=1}^ni\sigma(i)Id(n)=i=1∑n​iσ(i)
原式想用分块优化的话那么有last=nnilast=\frac{n}{\frac{n}{i}}last=in​n​有

=i=last+1n(Id(last)Id(i1))(2Φ(ni)1)=\sum_{i=last+1}^n(Id(last)-Id(i-1))(2*\Phi(\left \lfloor\frac{n}{i}\right \rfloor)-1)=i=last+1∑n​(Id(last)−Id(i−1))(2∗Φ(⌊in​⌋)−1)
Id(n)Id(n)Id(n)可以用线性筛处理一部分(先求每个数的约数个数再求前缀和的时候乘以i),大于的部分就用上面求的分块来处理了,欧拉函数求和用杜教筛即可
求完这个后最后的答案求一个快速幂就可以了,尽量都用int,不然会超时

#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int N=10000005;
int mod;
unordered_map<int,int> P;
unordered_map<int,int> D;
bool isP[N];
int prime[N];
int cnt;
int phi[N];
int d[N];
int num[N];
long long inv=500000004;
void init()
{
    phi[1]=d[1]=1;
    for(int i=2; i<N; i++)
    {
        if(!isP[i])
        {
            prime[cnt++]=i;
            phi[i]=i-1;
            d[i]=2;
            num[i]=1;
        }
        for(int j=0; j<cnt&&(ll)i*prime[j]<N; j++)
        {
            isP[i*prime[j]]=true;
            if(i%prime[j])
            {
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
                d[i*prime[j]]=d[i]*d[prime[j]];
                num[i*prime[j]]=1;
            }
            else
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                num[i*prime[j]]=num[i]+1;
                d[i*prime[j]]=d[i]/(num[i]+1)*(num[i*prime[j]]+1);
                break;
            }
        }
    }
    for(int i=1; i<N; i++)
    {
        phi[i]=(phi[i]+phi[i-1])%mod;
        d[i]=((ll)i*d[i]+d[i-1])%mod;
    }
}
int Sum(int x)
{
    if(x<N)return phi[x];
    if(P[x])return P[x];
    int ans=(x+1ll)*x/2%mod;
    for(int i=2,last; i<=x; i=last+1)
    {
        last=x/(x/i);
        ans=(ans-(last-i+1ll)*Sum(x/i)%mod+mod)%mod;
    }
    ans=((ll)ans+mod)%mod;
    P[x]=ans;
    return ans;
}
int Id(int n)
{
    if(n<N) return d[n];
    else if(D[n]) return D[n];
    int ans=0;
    for(int i=1,last; i<=n; i=last+1)
    {
        last=n/(n/i);
        ans=(ans+(last+i)*(last-i+1ll)/2%mod*((n/i*(n/i+1ll)/2)%mod)%mod)%mod;
    }
    D[n]=ans;
    return ans;
}
long long quickmod(long long a,long long b,long long p)
{
    long long ans=1;
    while(b)
    {
        if(b%2==1)
            ans=ans*a%p;
        a=a*a%p;
        b=b/2;
    }
    return ans;
}
int main()
{
    int n,m,p;
    scanf("%d%d%d",&n,&m,&p);
    mod=p-1;
    init();
    int ans=0;
    for(int i=1,last; i<=n; i=last+1)
    {
        last=n/(n/i);
        ans=(ans+(Id(last)-Id(i-1)+mod)%mod*((2ll*Sum(n/i)%mod-1ll+mod)%mod)%mod+mod)%mod;
    }
    printf("%lld\n",quickmod(m,ans,p));
    return 0;
}
/*
1000000000 999999997 98765431
*/

标签:约数,Provincial,Product,right,frac,gcd,sum,nd,lfloor
来源: https://blog.csdn.net/ftx456789/article/details/91346129

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有