杜教筛———神奇狄利克雷卷积———欧拉函数
Problem Description
One day, Master oy created a new function to celebrate his becoming a ‘huntian’ in majsoul.
f(n,a,b)=∑ni=1∑ij=1gcd(ia−ja,ib−jb)[gcd(i,j)=1]%(109+7)
Given n, a and b, Master oy wanted Newbie jj who was still a ‘chuxin’ to answer the value of f(n,a,b).
Input
There are multiple test cases.
The first line contains an integer T, indicating the number of test cases.
For each test case, there are three positive integers n, a and b which are separated by spaces. It’s guaranteed that a and b are coprime.
1≤n,a,b≤109
T=104, but there are only 10 test cases that n is over 106.
Output
For each test case, an integer in one line representing your answer.
Sample Input
2
1 2 3
100 2 3
Sample Output
0
101542
题意:求这个式子的值,通过写了几个互质的数观察,发现gcd那一坨等于i-j;然后打了一个表,第二个样例就是这样,于是与a,b无关。然后又打了一个表观察,发现的确有点规律,go on,感觉与欧拉函数有关,打个表,结论出来f(n)=f(n-1)+p(n)*n/2;(p为欧拉函数),于是转化为求f(n)=∑p(n)*n/2;话是这么说,可是隐隐感觉有写不对,于是把2乘过去,f(n)=f(n-1)+p(n)*n;
f(n)=∑p(n)*n-1;(f(1)=1;),于是先求f(n)=∑p(n)*n;
进入正题—–
杜教筛+狄利克雷卷积 再加一个链接
积性函数前缀和
官方题解为::::::
卷积之后为:f(n) = ∑i²-∑i*f(n/i);(后面需要能够整除),于是代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int Mod = 1e9+7;
const int maxn=1e6+10;
LL f[maxn];
LL Prime[maxn];
LL S[maxn];
bool vis[maxn];
int tot;
int n,a,b;
void init(){
f[1]=1;
int N=maxn-1;
for(int i=2;i<=N;i++){
if(!vis[i]){
Prime[tot++]=i;
f[i]=i-1;
}
for(int j=0;j<tot;j++){
if(i*Prime[j]>N){
break;
}
vis[i*Prime[j]]=true;
if(i%Prime[j]==0){
f[i*Prime[j]]=f[i]*Prime[j];
break;
}
else {
f[i*Prime[j]]=f[i]*f[Prime[j]];
}
}
}
S[1]=1;
for(int i=2;i<=N;i++) {
S[i]=(S[i-1]+1ll*f[i]*i%Mod)%Mod;
}
}
LL qpow(LL a,LL b) {
LL ans=1;
while (b) {
if(b&1) ans=ans*a%Mod;
a=a*a%Mod;
b/=2;
}
return ans;
}
map<int,LL>Sum;
LL inv6 = qpow (6,Mod-2);
LL GGG(LL n) {
if(n<maxn) return S[n];
if(Sum[n]) return Sum[n];
LL ans=1ll*n*(n+1)%Mod*(2*n+1)%Mod*inv6%Mod;
LL i,j;
for(i=2;i<=n;) {
j=n/(n/i);
//整除的一坨是连续的一些正整数,就是卷了之后有i,所以是下面
ans=(ans+Mod-((j+1)*j/2-1ll*i*(i-1)/2)%Mod*GGG (n/i)%Mod)%Mod;
i=j+1;
}
return Sum[n]=ans;;
}
int main () {
init ();
int qwq;
scanf ("%d",&qwq);
while (qwq--) {
scanf ("%d%d%d",&n,&a,&b);
LL ans=(GGG (n)-1+Mod)%Mod*qpow (2,Mod-2)%Mod;
printf("%lld\n",ans);
}
return 0;
}