http://acm.hdu.edu.cn/showproblem.php?pid=6390
昨天一下午,今天一上午,我已经快被这个题恶心死了。
TLE,TLE永远都是TLE。不得不说,我觉得卡我卡的没什么道理,非常的不爽!
卡内循环枚举变量类型我是真的不懂,发现知识盲区+1.
可是就算是再不爽也要含泪挖坑。
题意求:
(∑a=1m∑b=1nϕ(ab)ϕ(a)ϕ(b))mod(p)
(
∑
a
=
1
m
∑
b
=
1
n
ϕ
(
a
b
)
ϕ
(
a
)
ϕ
(
b
)
)
m
o
d
(
p
)
打表规律发现:
ϕ(ab)ϕ(a)ϕ(b)=gcd(a,b)ϕ(gcd(a,b))
ϕ
(
a
b
)
ϕ
(
a
)
ϕ
(
b
)
=
g
c
d
(
a
,
b
)
ϕ
(
g
c
d
(
a
,
b
)
)
所以就可以通过莫比乌斯反演来计算
∑a=1n∑b=1m[k=gcd(a,b)]
∑
a
=
1
n
∑
b
=
1
m
[
k
=
g
c
d
(
a
,
b
)
]
最后通过枚举 k k 并乘上和[ ϕ(k) ϕ ( k ) 的逆元]即可
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
ll phi[maxn];
ll mu[maxn];
ll inv[maxn];
ll a[maxn];
ll cnt;ll p;ll T;int n,m;
void get_inv(ll n){
inv[1]=1;
for(ll i=2;i<=n;i++){
inv[i]=(ll)(p-p/i)*inv[p%i]%p;
}
for(ll i=1;i<=n;i++){
a[i]=(ll)i*inv[phi[i]]%p;
}
}
void get_phi(){
for(ll i=1;i<maxn;i++){
phi[i]=i;
}
for(ll i=2;i<maxn;i++){
if(phi[i]==i){
for(ll j=i;j<maxn;j+=i)
phi[j]-=phi[j]/i;
}
}
}
void get_mu() {
mu[1] = 1;
for(int i=1;i<maxn;i++){
for(int j=2*i;j<maxn;j+=i){
mu[j]-=mu[i];
}
}
}
int main()
{
get_phi();
get_mu();
scanf("%lld", &T);
while (T--) {
scanf("%d%d%lld", &n, &m, &p);
if (n > m) swap(n, m);
ll res=min(n,m);
get_inv(res);
ll ans=0;
ll tmp=0;
for(ll d=1;d<=res;d++){
tmp=0;
//for (ll l = 1, r; l <= res; l = r + 1) {
// r = min(n / (n / l), m / (m / l));
// tmp += 1ll*(n / (l*d))*(m / (l* d))*(sum[r] - sum[l - 1])%p;
// }
int x=n/d,y=m/d;
ll tmp=0;
for(int j=1;j<=min(x,y);j++){
tmp+=(ll)mu[j]*(x/j)*(y/j);
tmp%=p;
}
ans+=tmp*a[d];
ans%=p;
}
printf("%lld\n", ans);
}
return 0;
}
神烦啊QAQ$!