链接
https://ac.nowcoder.com/acm/contest/549/J
题意
$\sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^2$ $(n,m\le 1e6)$
思路一
$\begin{aligned}
& \sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^2 \
= & \sum_{d=1}d^2\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d] \
\end{aligned}$
记 $f(d)=\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]$
记 $F(t)=\sum_{d\mid t}f(d)=\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor$
$f(d)=\sum_{d\mid t}\mu(\frac{t}{d})F(t)=\sum_{d\mid t}\mu(\frac{t}{d})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor$
枚举 $d$ 的倍数 $O(nlogn)$ 求解。
代码一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const LL MOD=1e9+7; const int N=1e6+5; int mn[N],mu[N]; VI p; void get_mu(int n) { mu[1]=1; for(int i=2;i<=n;i++) { if(!mn[i]) mn[i]=i,mu[i]=-1,p.PB(i); for(auto x:p) { if(x*i>n) break; mn[x*i]=x; if(i%x==0) {mu[x*i]=0;break;} mu[x*i]=-mu[i]; } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n,m;cin>>n>>m; get_mu(1e6); LL res=0; int lim=min(n,m); for(int i=1;i<=lim;i++) { for(int j=i;j<=lim;j+=i) { res=(res+1ll*i*i%MOD*mu[j/i]*(n/j)%MOD*(m/j)%MOD)%MOD; } } cout<<res<<'\n'; return 0; }
|
思路二
$\begin{aligned}
& \sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^2 \
= & \sum_{d=1}d^2\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d] \
= & \sum_{d=1}d^2\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1] \
\end{aligned}$
记 $g(n,m)=\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=1]=\sum_{d=1}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor$
记 $f(n,m)=\sum_{d=1}d^2g(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)$
做两次数论分块。
代码二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const LL MOD=1e9+7; const int N=1e6+5; int mn[N]; LL mu[N],sum[N]; VI p; void get_mu(int n) { mu[1]=1; for(int i=2;i<=n;i++) { if(!mn[i]) mn[i]=i,mu[i]=-1,p.PB(i); for(auto x:p) { if(x*i>n) break; mn[x*i]=x; if(i%x==0) {mu[x*i]=0;break;} mu[x*i]=-mu[i]; } } for(int i=1;i<=n;i++) mu[i]=(mu[i-1]+MOD+mu[i])%MOD; for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+1ll*i*i%MOD)%MOD; } LL g(int n,int m) { int lim=min(n,m); LL ret=0; for(int l=1,r;l<=lim;l=r+1) { r=min(n/(n/l),m/(m/l)); ret=(ret+(mu[r]+MOD-mu[l-1])%MOD*(n/l)%MOD*(m/l)%MOD)%MOD; } return ret; } LL f(int n,int m) { int lim=min(n,m); LL ret=0; for(int l=1,r;l<=lim;l=r+1) { r=min(n/(n/l),m/(m/l)); ret=(ret+(sum[r]+MOD-sum[l-1])%MOD*g(n/l,m/l)%MOD)%MOD; } return ret; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n,m;cin>>n>>m; get_mu(1e6); cout<<f(n,m)<<'\n'; return 0; }
|