设
h[n]
为
a∗b=0
的个数。
f[n]=n2−h[n]g[n]=∑m|nf[m]=∑m|n(m2−h[m])=∑m|nm2−∑m|nh[m]
对于
h[n]
h[n]=∑i=1n∑j=1n(gcd(i∗j,n)=n)=∑i=1n∑j|ngcd(i,n),1<=j<=n1=∑i=1ngcd(i,n)=∑i=1n∑d|gcd(i,n)ϕ(d)=∑d|nϕ(d)∑d|i,1<=i<=n1=∑d|nϕ(d)∗nd
显然 h[n] 是积性函数, ∑m|nh[m] 也是积性函数。
对于 n=pα 时。
∑m|nh[m]=∑m|n∑d|mϕ(d)∗nd=∑i=0α(pi+∑j=1i(pj−pj−1)pi−j)=∑i=0αpi+p−1p∑i=0αi∗pi=(α+1)pα
最后一步化简:错位相消。
设 n=pα11pα22...pαkk
∑m|nh[m]=(α1+1)∗(α2+1)∗...∗(αk+1)∗pα11∗pα22∗...∗pαkk=ϕ(n)∗n
所以:
g[n]=∑m|nm2−n∗ϕ(n)
暴力枚举m的值,总的复杂度是 o(n−−√) 。
小
trick
:
题目中要求对
264
取模,实际上就是用
unsigned long long
运算。
代码:
#include <bits/stdc++.h>
#define uLL unsigned long long
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
const int maxn = 100010;
int prime[maxn];
bool check[maxn];
void Get_Prime(){
memset(check,false,sizeof(check));
prime[0] = 0;
FOR(i,2,maxn){
if(!check[i]){
prime[++prime[0]] = i;
}
FOR(j,1,prime[0]+1){
if(i*prime[j] > maxn) break;
check[i*prime[j]] = true;
if(i%prime[j] == 0) break;
}
}
}
vector <uLL> fac;
int p[30],p_len,cnt[30];
void dfs(int wei,int u){
if(wei >= p_len) {fac.push_back(u); return;}
dfs(wei+1,u);
int q = p[wei];
FOR(i,0,cnt[wei]){
dfs(wei+1,u*q);
q = q*p[wei];
}
}
int n;
void work(){
uLL res = (uLL)n;
p_len = 0;
memset(cnt,0,sizeof(cnt));
FOR(i,1,prime[0]+1){
if(prime[i] > n/prime[i]) break;
if(n%prime[i] == 0) p[p_len++] = prime[i];
while(n%prime[i] == 0) {cnt[p_len-1] ++;n /= prime[i];}
}
if(n > 1) {p[p_len++] = n;cnt[p_len-1] = 1;}
FOR(i,0,p_len){
res *= ((uLL)cnt[i]+1);
}
fac.clear();
dfs(0,1);
uLL ans = 0;
FOR(i,0,(int)fac.size()){
uLL v = fac[i];
ans += v*v;
}
ans = ans - res;
cout<<ans<<endl;
}
int main(){
//freopen("test.in","r",stdin);
Get_Prime();
int T; scanf("%d",&T);
while(T--){
scanf("%d",&n);
work();
}
return 0;
}