题目链接:https://nanti.jisuanke.com/t/38226
题目大意:给定T组正整数n,求 ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n φ ( i ) φ ( j 2 ) φ ( k 3 ) φ ( i ) φ ( j ) φ ( k ) φ ( g c d ( i , j , k ) ) m o d 2 30 \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=1}^{n}\frac{\varphi(i)\varphi(j^2)\varphi(k^3)}{\varphi(i)\varphi(j)\varphi(k)}\varphi(gcd(i,j,k))\space mod\space 2^{30} i=1∑nj=1∑nk=1∑nφ(i)φ(j)φ(k)φ(i)φ(j2)φ(k3)φ(gcd(i,j,k)) mod 230 的值。
题解:看着很唬人,其实还是有套路的。。。
原式: ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n φ ( i ) φ ( j 2 ) φ ( k 3 ) φ ( i ) φ ( j ) φ ( k ) φ ( g c d ( i , j , k ) ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=1}^{n}\frac{\varphi(i)\varphi(j^2)\varphi(k^3)}{\varphi(i)\varphi(j)\varphi(k)}\varphi(gcd(i,j,k)) i=1∑nj=1∑nk=1∑nφ(i)φ(j)φ(k)φ(i)φ(j2)φ(k3)φ(gcd(i,j,k))
= ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n j k 2 φ ( g c d ( i , j , k ) ) =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=1}^{n}jk^2\varphi(gcd(i,j,k)) =i=1∑nj=1∑nk=1∑njk2φ(gcd(i,j,k))
= ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n j k 2 ∑ d = 1 n φ ( d ) [ g c d ( i , j , k ) = d ] =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\sum\limits_{k=1}^{n}jk^2\sum\limits_{d=1}^{n}\varphi(d)[gcd(i,j,k)=d] =i=1∑nj=1∑nk=1∑njk2d=1∑nφ(d)[gcd(i,j,k)=d]
= ∑ d = 1 n φ ( d ) d 3 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ ∑ k = 1 ⌊ n d ⌋ j k 2 [ g c d ( i , j , k ) = 1 ] =\sum\limits_{d=1}^{n}\varphi(d)d^3\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{k=1}^{\lfloor\frac{n}{d}\rfloor}jk^2[gcd(i,j,k)=1] =d=1∑nφ(d)d3i=1∑⌊dn⌋j=1∑⌊dn⌋k=1∑⌊dn⌋jk2[gcd(i,j,k)=1]
= ∑ d = 1 n φ ( d ) d 3 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ ∑ k = 1 ⌊ n d ⌋ j k 2 ε ( g c d ( i , j , k ) ) =\sum\limits_{d=1}^{n}\varphi(d)d^3\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{k=1}^{\lfloor\frac{n}{d}\rfloor}jk^2\varepsilon (gcd(i,j,k)) =d=1∑nφ(d)d3i=1∑⌊dn⌋j=1∑⌊dn⌋k=1∑⌊dn⌋jk2ε(gcd(i,j,k))
= ∑ d = 1 n φ ( d ) d 3 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ ∑ k = 1 ⌊ n d ⌋ j k 2 ∑ t ∣ i , t ∣ j , t ∣ k μ ( t ) =\sum\limits_{d=1}^{n}\varphi(d)d^3\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{k=1}^{\lfloor\frac{n}{d}\rfloor}jk^2\sum\limits_{t\mid i,t\mid j,t\mid k}\mu(t) =d=1∑nφ(d)d3i=1∑⌊dn⌋j=1∑⌊dn⌋k=1∑⌊dn⌋jk2t∣i,t∣j,t∣k∑μ(t)
= ∑ d = 1 n φ ( d ) d 3 ∑ t = 1 ⌊ n d ⌋ μ ( t ) t 3 ∑ i = 1 ⌊ n d t ⌋ ∑ j = 1 ⌊ n d t ⌋ ∑ k = 1 ⌊ n d t ⌋ j k 2 =\sum\limits_{d=1}^{n}\varphi(d)d^3\sum\limits_{t=1}^{\lfloor\frac{n}{d}\rfloor}\mu(t)t^3\sum\limits_{i=1}^{\lfloor\frac{n}{dt}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{dt}\rfloor}\sum\limits_{k=1}^{\lfloor\frac{n}{dt}\rfloor}jk^2 =d=1∑nφ(d)d3t=1∑⌊dn⌋μ(t)t3i=1∑⌊dtn⌋j=1∑⌊dtn⌋k=1∑⌊dtn⌋jk2
令 f ( x ) = ∑ t = 1 x μ ( t ) t 3 ∑ i = 1 ⌊ x t ⌋ ∑ j = 1 ⌊ x t ⌋ ∑ k = 1 ⌊ x t ⌋ j k 2 f(x)=\sum\limits_{t=1}^{x}\mu(t)t^3\sum\limits_{i=1}^{\lfloor\frac{x}{t}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{x}{t}\rfloor}\sum\limits_{k=1}^{\lfloor\frac{x}{t}\rfloor}jk^2 f(x)=t=1∑xμ(t)t3i=1∑⌊tx⌋j=1∑⌊tx⌋k=1∑⌊tx⌋jk2 ,函数前半部分的 μ ( t ) t 3 \mu(t)t^3 μ(t)t3 可以利用前缀和数组求值,后半部分可以利用数论分块加速。那么可以令原式为函数 g ( x ) g(x) g(x) ,则有 g ( x ) = ∑ d = 1 x φ ( x ) x 3 f ( ⌊ x d ⌋ ) g(x)=\sum\limits_{d=1}^{x}\varphi(x)x^3f(\lfloor\frac{x}{d}\rfloor) g(x)=d=1∑xφ(x)x3f(⌊dx⌋) ,同样的,这个函数的前半部分可以通过前缀和求出,后半部分也可以利用数论分块加速。
下面是AC代码。
#include
#include
#include
#include
using namespace std;
#define debug(x) cerr<<#x<<":"<
#define debug2(x,y) cerr<<#x<<":"<
#define debug3(x,y,z) cerr<<#x<<":"<
typedef long long ll;
struct fastio{
fastio(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
}fio;
const int N=1e7+5;
const int M=1<<30;
const int INV3=1789569707;
vector<int> prime,part,mu,s1,s2,phi;
void init(){
phi=s1=s2=part=vector<int>(N,0);
mu=vector<int>(N,-1);
s1[1]=s2[1]=phi[1]=mu[1]=1;
for(ll i=2;i<N;++i){
s2[i]=((((ll)mu[i]*i*i)%M*i)%M+M+(ll)s2[i-1])%M;
if(!part[i]){
prime.push_back(i);
part[i]=i;
phi[i]=i-1;
}
s1[i]=((((((ll)phi[i]*i)%M)*i)%M*i)%M+(ll)s1[i-1])%M;
for(auto j:prime){
if(i*j>=N) break;
part[i*j]=j;
if(i%j==0){
mu[i*j]=0;
phi[i*j]=((ll)j*(ll)phi[i])%M;
break;
}
else{
mu[i*j]=-mu[i];
phi[i*j]=((ll)phi[i]*(ll)phi[j])%M;
}
}
}
}
unordered_map<int,int> f_v;
ll f(ll x){
if(f_v[x]) return f_v[x];
ll res=0;
for(ll l=1,r;l<=x;l=r+1){
r=x/(x/l);
ll y=((ll)(1+x/l)*(x/l)>>1ll)%M;
res=(res+((s2[r]-s2[l-1])%M*((ll)(x/l)*y%M*y%M*(((ll)(x/l)<<1ll)+1)%M*INV3%M)+M)%M)%M;
}
return f_v[x]=res;
}
int g(ll x){
int res=0;
for(ll l=1,r;l<=x;l=r+1){
r=x/(x/l);
res=((res+(ll)(s1[r]-s1[l-1])%M*f(x/l)%M)%M+M)%M;
}
return res;
}
signed main(){
int t,n;
cin>>t;
init();
while(t--){
cin>>n;
cout<<g(n)<<endl;
}
}
要注意的是,我们可以利用map对 f ( x ) f(x) f(x) 的值进行储存,避免不必要的计算(如果不用map会TLE的说)。同时结果要返回正整数值,否则会WA。
(勉勉强强卡过了吧。。。)