P3327 [SDOI2015] 约数个数和 题解
P3327 [SDOI2015] 约数个数和
题意:
设 \(d(x)\) 为 \(x\) 的约数个数,给定 \(n,m\),求
思路:
\(\displaystyle \sum_{i=1}^n\sum_{j=1}^md(ij)=\sum_{i=1}^n\sum_{j=1}^m \sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]\)
\(\displaystyle =\sum_{x=1}^n\sum_{y=1}^m \lfloor\frac{n}{x} \rfloor\lfloor\frac{m}{y} \rfloor[\gcd(x,y)=1]\)
\(\displaystyle =\sum_{x=1}^n\sum_{y=1}^m \lfloor\frac{n}{x} \rfloor\lfloor\frac{m}{y} \rfloor\sum_{d|\gcd(x,y)}\mu(d)\)
\(\displaystyle =\sum_{x=1}^n\sum_{y=1}^m \lfloor\frac{n}{x} \rfloor\lfloor\frac{m}{y} \rfloor\sum_{d=1}^{n}[d|x][d|y]\mu(d)\)
\(\displaystyle =\sum_{d=1}^{n}\mu(d)(\sum_{x=1}^n\lfloor\frac{n}{x} \rfloor[d|x])(\sum_{y=1}^m \lfloor\frac{m}{y} \rfloor[d|y])\)
\(\displaystyle =\sum_{d=1}^{n}\mu(d)(\sum_{x=1}^{\lfloor\frac{n}{d} \rfloor}\lfloor\frac{\lfloor\frac{n}{d} \rfloor}{x} \rfloor)(\sum_{y=1}^{\lfloor\frac{m}{d} \rfloor}\lfloor\frac{\lfloor\frac{m}{d} \rfloor}{y} \rfloor)\)
然后直接计算即可。
代码
点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define double long double
#define PII pair<int,int>
using namespace std;
mt19937_64 rng(time(0));
const int N = 1e6 + 10, M = 1e3, mod = 19940417;
const double EPS = 1e-8;
int qpow(int x, int n) {
int ans = 1;
while (n) {
if (n & 1) {
ans *= x;
ans %= mod;
}
x *= x;
x %= mod;
n >>= 1;
}
return ans;
}
//int fac[N];
//int inv[N];
//void init(){
// fac[0]=inv[0]=1;
// for(int i=1;i<N;i++){
// fac[i]=fac[i-1]*i%mod;
// }
// inv[N-1]=qpow(fac[N-1],mod-2);
// for(int i=N-2;i>=0;i--){
// inv[i]=inv[i+1]*(i+1)%mod;
// }
//}
//
//
//int C(int n,int m){
// return fac[n]*inv[m]%mod*inv[n-m]%mod;
//}
int mu[N], p[N],smu[N];
bool flg[N];
int tot = 0;
void getMu(int n) {
mu[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!flg[i]) p[++tot] = i, mu[i] = -1;
for (int j = 1; j <= tot && i * p[j] <= n; ++j) {
flg[i * p[j]] = 1;
if (i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = -mu[i];
}
}
for(int i=2;i<=n;i++){
mu[i]+=mu[i-1];
}
}
ll H(int n){
ll res=0;
int l=1,r;
while(l<=n){
r=n/(n/l);
res+=(ll)(r-l+1)*(n/l);
l=r+1;
}
return res;
}
ll h[N];
ll H1(int n,int m){
ll res=0;
int l=1,r;
while(l<=n&&l<=m){
r=min(n/(n/l),m/(m/l));
res+=(mu[r]-mu[l-1])*h[n/l]*h[m/l];
l=r+1;
}
return res;
}
void solve() {
int n,m;
cin>>n>>m;
ll ans=H1(n,m);
cout<<ans<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
cin >> t;
// init();
getMu(5e4);
for(int i=1;i<=5e4;i++){
h[i]=H(i);
}
while (t--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号