题目大意
一个置换可以看成是有
a
1
a_1
a1 个长度为
1
1
1 的环 +
a
2
a_2
a2 个长度为
2
2
2 的环 + …… +
a
n
a_n
an 个长度为
n
n
n 的环,满足
∑
i
=
1
n
i
⋅
a
i
=
n
\sum_{i=1}^n i\cdot a_i=n
∑i=1ni⋅ai=n 。
记
f
(
a
1
,
a
2
,
⋯
,
a
n
)
f(a_1,a_2,\cdots,a_n)
f(a1,a2,⋯,an) 表示各种环的数量分别为
a
1
,
⋯
,
a
n
a_1,\cdots,a_n
a1,⋯,an、长度为
n
n
n 的置换的数量,现给定
n
,
p
n,p
n,p(
p
p
p 是质数),问有多少种不同的数列
a
1
,
⋯
,
a
n
a_1,\cdots,a_n
a1,⋯,an,满足
p
∤
f
(
a
1
,
a
2
,
⋯
,
a
n
)
p \not|\ f(a_1,a_2,\cdots,a_n)
p∣ f(a1,a2,⋯,an) 。
n
≤
1
0
18
,
2
≤
p
≤
1
0
5
n \leq 10^{18},~~2 \leq p \leq 10^5
n≤1018, 2≤p≤105
多测,
T
≤
1
0
5
T \leq 10^5
T≤105,2s
\\
\\
\\
题解
明眼人一看就有
f
(
a
1
,
⋯
,
a
n
)
=
n
!
∏
i
=
1
n
i
a
i
⋅
a
i
!
f(a_1,\cdots,a_n)=\frac{n!}{\prod_{i=1}^n i^{a_i} \cdot a_i!}
f(a1,⋯,an)=∏i=1niai⋅ai!n!
所以
p
p
p 不整除这个东西,意思是要让分母的
p
p
p 因子数量
≥
\ge
≥ 分子的
p
p
p 因子数量。
乍一看这个
n
n
n 这么大,整数拆分、dp 之类的啥都做不了,吓死个人。
冷静分析.jpg
首先,这整个分式最终必然得到一个整数(因为这是在计算方案数),这意味着分母的
p
p
p 因子数量一定是
≤
\leq
≤ 分子的
p
p
p 因子数量的。而我们的目标又是“分母的
p
p
p 因子数量
≥
\ge
≥ 分子的
p
p
p 因子数量”,因此可得:1、我们要让分母、分子的
p
p
p 因子数量相等;2、这等价于让分母的
p
p
p 因子数量最大化。
有了这个目标,就能隐约感觉到,
a
a
a 数列不会长得太奇怪,肯定有限制的。
接下来就来排除掉一些情况。
- 会不会有环长
r
>
p
r>p
r>p 却又不是
p
p
p 的倍数呢?
注意到这时候 r a r r^{a_r} rar 是没有贡献的,这太浪费了,我们把这 a r a_r ar 个长度为 r r r 的环,每个抽 p p p 出来,组成 a r a_r ar 个长度为 p p p 的环,发现贡献至少多了 a r a_r ar。说明这种情况下分母的 p p p 因子数量没有最大化。 - 会不会有环长
r
=
k
p
r=kp
r=kp(
k
>
1
k>1
k>1)呢?
同理啊,全部换成环长为 p p p 会使贡献增大:单个 r r r 的贡献从 1 + ( k 的 p 因 子 数 量 ) 1+(k的p因子数量) 1+(k的p因子数量) 变成 k k k,正常情况下后者都会大于前者;而 a r ! a_r! ar! 部分的贡献从 a r ! a_r! ar! 变成 ( a p + a r ) ! a p ! \frac{(a_p+a_r)!}{a_p!} ap!(ap+ar)!,不会更劣。
唯一使得单个 r r r 贡献保持不变的是 k = p = 2 k=p=2 k=p=2,但这会在 a r ! a_r! ar! 部分增大贡献。
所以也不合法。
所以这就说明 a i a_i ai 非零的只有 i ∈ [ 1 , p ] i \in [1,p] i∈[1,p] 了。
我们可以先想像一种初始情况: a 1 = n a_1=n a1=n,这显然是一个合法解。然后看看怎么能把 a 1 a_1 a1 里的东西拿到 a 2 , ⋯ , a p a_2,\cdots,a_p a2,⋯,ap 里去,而保持 p p p 因子数量不变。
先考虑
n
m
o
d
p
=
0
n \bmod p=0
nmodp=0。
当然可以想到
a
1
a_1
a1 举家迁移到
a
p
a_p
ap,贡献从
∑
j
=
1
∞
⌊
n
p
j
⌋
\sum_{j=1}^\infty \lfloor \frac{n}{p^j} \rfloor
∑j=1∞⌊pjn⌋ 变成
n
p
+
∑
j
=
2
∞
⌊
n
p
j
⌋
\frac np + \sum_{j=2}^\infty \lfloor \frac{n}{p^j} \rfloor
pn+∑j=2∞⌊pjn⌋,没有变化。如果只是抽
a
1
a_1
a1 的一部分放到
a
p
a_p
ap 里去呢?由于在
p
p
p 的幂的位置,
a
1
!
a_1!
a1! 的
p
p
p 因子数量都会有一次大的提升,所以构成
p
p
p 的幂的连续段不能拆开考虑,否则
p
p
p 因子数量一定会减少。比如
a
1
=
14
,
p
=
2
a_1=14, p=2
a1=14,p=2,那么相当于把
a
1
a_1
a1 分成长度为
8
,
4
,
2
8,4,2
8,4,2 的三个段,每个段要么留在
a
1
a_1
a1 要么搬到
a
p
a_p
ap
更一般地说,设
n
n
n 的
p
p
p 进制表示为
b
1
b
2
⋯
b
m
b_1b_2\cdots b_m
b1b2⋯bm,那么每个二进制位下的每个单位“1”可以选择留在
a
1
a_1
a1 或搬到
a
p
a_p
ap,因此对答案的贡献为
∏
i
=
1
m
−
1
(
b
i
+
1
)
\prod_{i=1}^{m-1}(b_i+1)
∏i=1m−1(bi+1)。(为啥是
m
−
1
m-1
m−1?最低位一定是
0
0
0,如果不是
0
0
0 的话是下面的情况)
再考虑
n
m
o
d
p
>
0
n \bmod p>0
nmodp>0。
显然这个多出来的部分放哪都无所谓,都不会产生任何
p
p
p 因子,因此这里对答案的贡献是
n
m
o
d
p
n \mod p
nmodp 的可重整数拆分。
综上,答案为
a
n
s
=
p
a
r
t
(
n
m
o
d
p
)
⋅
∏
i
=
1
m
−
1
(
b
i
+
1
)
ans=part(n \bmod p) \cdot \prod_{i=1}^{m-1}(b_i+1)
ans=part(nmodp)⋅i=1∏m−1(bi+1)
其中 b 1 b 2 ⋯ b m b_1b_2\cdots b_m b1b2⋯bm 是 n n n 的 p p p 进制表示, p a r t part part 表示可重整数拆分方案数。后者五边形数 O ( n n ) O(n \sqrt n) O(nn) 或者 O ( n log n ) O(n \log n) O(nlogn) 预处理一下就完事了。
代码
#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long LL;
const int maxp=1e5+5;
const LL mo=1e9+7;
LL n;
int p;
int w[maxp],w0;
LL f[maxp];
void Pre_part(int n)
{
for(int i=1; w[w0]<n; i++)
{
w[++w0]=i*(3*i-1)>>1;
w[++w0]=i*(3*i+1)>>1;
}
f[0]=1;
fo(i,1,n)
for(int j=1; w[j]<=i; j++) (f[i]+=((((j-1)>>1)&1) ?-1 :1)*f[i-w[j]])%=mo;
}
int T;
int main()
{
Pre_part(1e5);
scanf("%d",&T);
fo(ti,1,T)
{
scanf("%lld %d",&n,&p);
LL ans=f[n%p];
for(n/=p; n; n/=p) (ans*=n%p+1)%=mo;
printf("Case #%d: %lld\n",ti,(ans+mo)%mo);
}
}