P4240 毒瘤之神的考驗
阿新 • • 發佈:2020-12-26
P4240 毒瘤之神的考驗
連結
題解
假定\(n \leq m\) ,(交換n,m顯然不影響答案)
首先尤拉函式有個性質。。 \(\phi(xy)\) \(=\) \(\frac{\phi(x) \phi(y) (x,y)}{\phi((x,y))}\)
代入題目 \(\sum_{x=1}^{n}\sum_{y=1}^{m}\frac{\phi(x) \phi(y) (x,y)}{\phi((x,y))}\)
然後是喜聞樂見的列舉公因數,在轉化為莫比烏斯函式。。。
\(\sum_{d=1}^{n}\sum_{t=1}^{\lfloor \frac{n}{d} \rfloor} \frac{d\mu(t)}{\phi(d)} \sum_{x=1}^{\lfloor \frac{n}{dt}\rfloor}
\phi(xtd) \sum_{y=1}^{\lfloor \frac{m}{dt}\rfloor}\phi(ytd)\)
我們設:
\(A(p)\) \(=\) \(\sum_{d|p}\frac{d}{\phi(d)} \mu(\frac{p}{d})\)
\(D(x,p)\) \(=\) \(\sum_{i=1}^{x}\phi(ip)\)
於是答案可以表示為 \(\sum_{p=1}^{n}A(p)D(\lfloor \frac{n}{p} \rfloor,p)D(\lfloor \frac{m}{p} \rfloor,p)\)
\(A(p),D(x,p)\)兩種函式都是可以\(O(nlogn)\)預處理出來的,於是此時我們已經得到\(O(nlogn+qn)\)的做法了
我們需要進一步優化單次詢問的效率。
設 \(S(lim,x,y)\)
如果對於任意\(S(lim,x,y)\)都能\(O(1)\)詢問的話,就可以套用整除分塊了。。。然而這並不容易做到。
我們可以先預處理一些\(S(lim,x,y)\),這樣對於部分p值就能快速詢問了。
假設我們預處理出所有滿足\(x,y \leq B\)的資料,那麼對於 \(\lfloor \frac{m}{p} \rfloor \leq B\) 的都可以\(O(1)\)詢問,這部分效率是\(O(n^{0.5})\)的
對於\(\lfloor \frac{m}{p} \rfloor > B\) 的情況,這樣的p是滿足\(p<\lfloor \frac{m}{B} \rfloor\)
於是總效率就是\(O(nlogn+q(n^{0.5}+\lfloor \frac{m}{B} \rfloor))\)
\(Code\)
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+10;
const LL P=998244353;
const int E=90;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(LL x){
if(x>9) print(x/10);
putchar(x%10+'0');
}
LL qpow(LL x,LL y,LL p){
LL re=1;
while(y){
if(y&1) re=re*x%p;
x=x*x%p;y>>=1;
}
return re;
}
int n,m;
LL phi[N],mu[N];
LL ni_phi[N];
LL A[N];
vector<LL> D[N],S[100][100];
bool is_pri[N+10];
int pri[N],cntp=0;
void init_pri(){
mu[1]=1;phi[1]=1;
for(int i=2;i<=100000;++i){
if(!is_pri[i]) {
pri[++cntp]=i;
mu[i]=P-1;
phi[i]=i-1;
}
for(int j=1;j<=cntp&&pri[j]*i<=100000;++j){
is_pri[pri[j]*i]=1;
if(i%pri[j]==0) {
phi[pri[j]*i]=phi[i]*pri[j];
mu[pri[j]*i]=0;
break;
}
else{
phi[pri[j]*i]=phi[i]*(pri[j]-1);
mu[pri[j]*i]=P-mu[i];
}
}
}
}
int main(){
init_pri();
for(int i=1;i<=100000;++i) ni_phi[i]=qpow(phi[i],P-2,P);
LL x,y;
for(int i=1;i<=100000;++i){
x=(LL)i*ni_phi[i]%P;
for(int j=1;j<=100000/i;++j){
A[i*j]+=x*mu[j]%P;
}
A[i]=A[i]%P;
}
for(int p=1;p<=100000;++p){
x=0;D[p].push_back(x);
for(int i=1;i<=100000/p;++i){
x+=phi[i*p];
if(x>=P)x-=P;
D[p].push_back(x);
}
}
for(int i=1;i<=E;++i){
for(int j=1;j<=i;++j){
x=0;S[i][j].push_back(x);
for(int p=1;p<=100000/i;++p){
x+=A[p]*D[p][i]%P*D[p][j]%P;
if(x>=P)x-=P;
S[i][j].push_back(x);
}
}
}
int T,k,l;scanf("%d",&T);
LL ans;
while(T--){
scanf("%d%d",&n,&m);ans=0;
if(n>m) swap(n,m);
for(int i=1,j;i<=n;i=j+1){
j=i;
l=n/i;k=m/i;
if(k>E){
ans+=A[i]*D[i][l]%P*D[i][k]%P;
}
else{
j=min(n/l,m/k);
ans+=(S[k][l][j]-S[k][l][i-1]+P)%P;
}
}
ans=(ans%P+P)%P;
printf("%lld\n",ans);
}
return 0;
}