题目链接
我错了,杜教筛不是只背板子就够的qwq
跟着神仙yyb推了一遍式子,感觉这题还是很神仙
题意是求
显然先把gcd枚举一下,假设gcd(i,j)==k
原式就为
后面这个式子根据套路可以往外提一下
这样子看着一脸可莫比乌斯反演的样子
令
根据某引理
换过来枚举d
后面那玩意可以O(1)算的
反演完了,我们把它代回去
令
枚举g,再随便枚举个k
有些项可以消掉
显然
可以提出来
显然前面可以整除分块
主要需要快速求出后面的
这时候狄利克雷卷积就有用了
常见的几个狄利克雷卷积
显然这里我们需要用的是
卷完以后我们可以得到
这时候需要计算上面函数的前缀和
,那么就是杜教筛的套路
看看要卷的东西
显然令
就可以把
消掉
这个前缀和用杜教筛处理之后,总复杂度是
代码如下:
#include<bits/stdc++.h>
#define N 8000000
using namespace std;
long long phi[N+10];
int p[N+10];
bool vis[N+10];
long long n,cnt,mod,inv2,inv6;
map<long long,long long> m;
long long kasumi(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void init()
{
phi[1]=1;
for(int i=2;i<=N;i++)
{
if(!vis[i])
{
p[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt;j++)
{
if(i*p[j]>N) break;
vis[i*p[j]]=1;
if(!(i%p[j])) {phi[i*p[j]]=phi[i]*p[j];break;}
else phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
for(int i=1;i<=N;i++) phi[i]=(phi[i]*i%mod*i%mod+phi[i-1])%mod;
}
inline long long sum2(long long x)
{
x%=mod;
return x*(x+1)%mod*(x+x+1)%mod*inv6%mod;
}
inline long long sum3(long long x)
{
x%=mod;
return x*(x+1)%mod*inv2%mod;
}
long long solve(long long x)
{
if(x<=N) return phi[x];
if(m.count(x)) return m[x];
long long res=sum3(x);
res=res*res%mod;
for(long long l=2,r;l<=x;l=r+1)
{
r=(x/(x/l));
long long tmp=(sum2(r)-sum2(l-1));
res-=tmp*solve(x/l);
res%=mod;
}
return m[x]=(res+mod)%mod;
}
int main()
{
scanf("%lld%lld",&mod,&n);
inv2=kasumi(2,mod-2);
inv6=kasumi(6,mod-2);
init();
long long ans=0;
for(long long l=1,r;l<=n;l=r+1)
{
r=(n/(n/l));
long long tmp=sum3(n/l);
tmp=tmp*tmp%mod;
long long res=(solve(r)-solve(l-1))%mod;
ans+=res*tmp%mod;
ans%=mod;
}
printf("%lld\n",(ans+mod)%mod);
}