题目描述
あの日の悲しみさえ
那一天的悲伤也好
あの日の苦しみさえ
那一天的痛苦也好
そのすべてを愛してた あなたとともに
我深爱着和你在一起的点点滴滴
胸に残り離れない
残留在心中久久不离
苦いレモンの匂い
苦柠檬的香气
雨が降り止むまでは帰れない
雨停为止都无法回去
切り分けた果実の片方の様に
如同切开的果实的一面那样
今でもあなたはわたしの光
至今为止你依然是我的光
米津玄师—《Lemon》
题目描述
旧日的美好已如昙花般绽放之后消失的无影无踪,只剩下些许的回忆和无穷的悔恨。如梦般的时光已经逝去,但值得庆幸的是,仍有电脑、鼠标、键盘和那一串串的公式无言却忠诚地记录着过去。
小D在时光的缝隙中找到了一个公式
解析
x
=
∏
i
=
1
q
p
i
k
i
,
g
(
x
)
=
∑
i
=
1
q
k
i
,
g
(
1
)
=
1
x=\prod_{i=1}^qp_i^{k_i},g(x)=\sum_{i=1}^qk_i,g(1)=1
x=∏i=1qpiki,g(x)=∑i=1qki,g(1)=1
g
(
p
r
i
m
e
)
=
1
,
g
(
a
×
p
r
i
m
e
)
=
g
(
a
)
+
1
g(prime)=1,g(a\times prime)=g(a)+1
g(prime)=1,g(a×prime)=g(a)+1所以线性筛的时候,可以顺便把
g
(
n
)
g(n)
g(n)给筛出来。
入门推荐:here
原式子:
∏
i
=
1
n
∏
j
=
1
m
g
(
g
c
d
(
i
,
j
)
)
\prod_{i=1}^n\prod_{j=1}^m g(gcd(i,j))
i=1∏nj=1∏mg(gcd(i,j))
提取
g
c
d
gcd
gcd:
∏
d
=
1
n
g
(
d
)
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
d
]
\prod_{d=1}^n g(d)^{\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=d]}
d=1∏ng(d)∑i=1n∑j=1m[gcd(i,j)=d]
反演一下指数那个式子:
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
d
]
=
∑
i
=
1
n
d
∑
j
=
1
m
d
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
i
=
1
n
d
∑
j
=
1
m
d
∑
k
∣
g
c
d
(
i
,
j
)
μ
(
k
)
\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=d]=\sum_{i=1}^{\frac nd}\sum_{j=1}^{\frac md}[gcd(i,j)=1]=\sum_{i=1}^{\frac nd}\sum_{j=1}^{\frac md}\sum_{k|gcd(i,j)}\mu(k)
i=1∑nj=1∑m[gcd(i,j)=d]=i=1∑dnj=1∑dm[gcd(i,j)=1]=i=1∑dnj=1∑dmk∣gcd(i,j)∑μ(k)
得到这个式子:
∏
d
=
1
n
g
(
d
)
∑
k
=
1
n
d
μ
(
k
)
n
k
d
m
k
d
\prod_{d=1}^n g(d)^{\sum_{k=1}^{\frac nd}\mu(k)\frac{n}{kd}\frac{m}{kd}}
d=1∏ng(d)∑k=1dnμ(k)kdnkdm
上面这个式子可以
O
(
n
)
O(n)
O(n)求值了,但是还不够,因为这题有多组数据。
想到一个常用的优化方式:
先把指数提下来:
∏
d
=
1
n
∏
k
=
1
n
d
g
(
d
)
μ
(
k
)
n
k
d
m
k
d
\prod_{d=1}^n \prod_{k=1}^{\frac nd} g(d)^{\mu(k)\frac{n}{kd}\frac{m}{kd}}
d=1∏nk=1∏dng(d)μ(k)kdnkdm
令
T
=
k
d
T=kd
T=kd,换元求积:
∏
T
=
1
n
∏
d
∣
T
g
(
d
)
μ
(
T
d
)
n
T
m
T
\prod_{T=1}^n\prod_{d|T}g(d)^{\mu(\frac Td)\frac nT \frac mT}
T=1∏nd∣T∏g(d)μ(dT)TnTm
再变换一下:
∏
T
=
1
n
(
∏
d
∣
T
g
(
d
)
μ
(
T
d
)
)
n
T
m
T
\prod_{T=1}^n(\prod_{d|T}g(d)^{\mu(\frac Td)})^{\frac nT \frac mT}
T=1∏n(d∣T∏g(d)μ(dT))TnTm
发现这个式子
∏
d
∣
T
g
(
d
)
μ
(
T
d
)
\prod_{d|T}g(d)^{\mu(\frac Td)}
∏d∣Tg(d)μ(dT)可以
O
(
n
l
o
g
(
n
)
)
O(nlog(n))
O(nlog(n))预处理出来,
O
(
1
)
O(1)
O(1)求值。
所以最后总的复杂度是 O ( ( n l o g ( n ) + T n ) × 常 数 ) O((nlog(n)+T\sqrt n)\times常数) O((nlog(n)+Tn)×常数)
AC_CODE:
#include<bits/stdc++.h>
#define fi first
#define se second
#define iis std::ios::sync_with_stdio(false);cin.tie(0)
#define pb push_back
#define o2(x) (x)*(x)
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int MXN = 3e5 + 6;
int n, q, m;
int noprime[MXN], pp[MXN/2], pcnt;
int mu[MXN];
LL g[MXN], inv_g[MXN], f[MXN], pre[MXN], inv_pre[MXN];
LL ksm(LL a, LL b) {
LL res = 1;
for(;b;b>>=1,a=a*a%MOD) {
if(b&1) res=res*a%MOD;
}
return res;
}
void init_rime() {
noprime[0] = noprime[1] = 1;
mu[1] = g[1] = 1;
for(int i = 2; i < MXN; ++i) {
if(!noprime[i]) pp[pcnt++] = i, mu[i]=-1, g[i] = 1;
for(int j = 0; j < pcnt && i*pp[j] < MXN; ++j) {
noprime[i*pp[j]] = 1;
mu[i*pp[j]] = -mu[i];
g[i*pp[j]] = g[i] + 1;
if(i % pp[j] == 0) {
mu[i*pp[j]] = 0;
break;
}
}
}
for(int i = 1; i < MXN; ++i) f[i] = 1, inv_g[i] = ksm(g[i], MOD-2);
for(int i = 2; i < MXN; ++i) {
for(int j = i; j < MXN; j += i) {
if(mu[j/i] == 1) f[j] = f[j] * g[i] % MOD;
else if(mu[j/i] == -1) f[j] = f[j] * inv_g[i] % MOD;
}
}
pre[0] = pre[1] = inv_pre[0] = inv_pre[1] = 1;
for(int i = 2; i < MXN; ++i) {
pre[i] = pre[i-1] * f[i] % MOD;
inv_pre[i] = ksm(pre[i], MOD-2);
}
}
int main(int argc, char const *argv[]) {
init_rime();
int tim;
scanf("%d", &tim);
while(tim --) {
scanf("%d%d", &n, &m);
LL ans = 1, tmp;
if(n > m) swap(n, m);
for(int L = 1, R; L <= n; L = R + 1) {
R = min(n/(n/L),m/(m/L));
ans = (ans * ksm(pre[R]*inv_pre[L-1]%MOD, 1LL*(n/L)*(m/L)%(MOD-1)))%MOD;
}
printf("%lld\n", ans);
}
return 0;
}
题目类似:bzoj 4816: [Sdoi2017]数字表格