题目vj链接
题面:

题意:
求解:
g(m)=m∣n∑f(m),f(m)=a=0∑m−1b=0∑m−1[a∗b%m=0]。
题解:
①先化简 f(m):
f(m)=a=0∑m−1b=0∑m−1[a∗b%m=0]
f(m)=m2−a=0∑m−1b=0∑m−1[a∗b%m=0]
f(m)=m2−a=1∑mb=1∑m[a∗b%m=0](a=0与a=m的贡献一致,b=0与b=m的贡献一致)
设 p(m)=a=1∑mb=1∑m[a∗b%m=0]
②求解 p(m):
p(m)=a=1∑mb=1∑m[a∗b%m=0]
=a=1∑mb=1∑mm∣(a∗b)
=a=1∑mb=1∑mgcd(m,a)m∣(gcd(m,a)a∗b)
=a=1∑mb=1∑mgcd(m,a)m∣b ,因为 gcd(gcd(m,a)m,gcd(m,a)a)=1
=a=1∑mgcd(a,m)mm
=a=1∑mgcd(a,m)
=d=1∑ma=1∑m[gcd(a,m)=d]∗d
=d∣m∑a=1∑m[gcd(a,m)=d]∗d
=d∣m∑d∗a=1∑dm[gcd(a,dm)=1]
=d∣m∑d∗φ(dm)
③带入 g(n):
g(m)=m∣n∑f(m)
=m∣n∑(m2−d∣m∑d∗φ(dm))
我们令 a(n)=m∣n∑m2, b(n)=m∣n∑d∣m∑d∗φ(dm), g(n)=a(n)−b(n)
④求解 a(n):
我们知道除数函数 σ(k,x)=d∣x∑dk是积性函数,即若 gcd(x,y)==1,则 σ(k,x∗y)=σ(k,x)∗σ(k,y)
我们设 σ(2,n)=d∣n∑d2
将n唯一分解 n=p1e1∗p2e2∗...∗pkek
其中 (p1e1,p2e2,...,pkek) 两两互质
σ(2,n)=σ(2,p1e1)∗σ(2,p2e2)∗...∗σ(2,pkek)
对于 σ(2,piei)=(pi0)2+(pi1)2+...+(piei)2
我们可以看作 a1=1,q=pi2 的等比数列求和。这样 O(1)即可求解。
因为这题要求对 264 取模,逆元不好处理,直接暴力计算即可。(因为 ei不会很大)
⑤求解 b(n):
b(n)=m∣n∑d∣m∑d∗φ(dm)
先枚举 d
b(n)=d∣n∑d∗d∣m,m∣n∑φ(dm)
=d∣n∑d∗(k∗d)∣n∑φ(k)
=d∣n∑d∗k∣dn∑φ(k)
n 的因子的欧拉函数之和为 n
b(n)=d∣n∑d∗dn=d∣n∑n=n∗σ(0,n)=n∗∏(ei+1)
⑥综上:
g(n)=σ(2,n)−n∗∏(ei+1)
时间复杂度 O(T∗n )
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=10007;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int maxp=100100;
const int up=100100;
int prime[maxn],cnt=0;
bool ha[maxn];
int p[55],e[55],tot=0;
void Prime(void)
{
ha[1]=true;
for(int i=2;i<maxn;i++)
{
if(!ha[i])
prime[++cnt]=i;
for(int j=1;j<=cnt&&prime[j]*i<maxn;j++)
{
ha[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
void only(int n)
{
memset(e,0,sizeof(e));
tot=0;
for(int i=1;prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]) continue;
p[++tot]=prime[i];
while(n%prime[i]==0)
e[tot]++,n/=prime[i];
}
if(n>1) p[++tot]=n,e[tot]=1;
}
int main(void)
{
Prime();
int tt,n;
scanf("%d",&tt);
while(tt--)
{
scanf("%d",&n);
only(n);
llu a=1,b=n;
for(int i=1;i<=tot;i++)
{
b*=(e[i]+1);
llu ans=1,pk=1;
for(int j=1;j<=e[i];j++)
pk=pk*p[i],ans=ans+pk*pk;
a*=ans;
}
printf("%llu\n",a-b);
}
return 0;
}