题目大意
圆周上均匀地放着n个点,你可以将若干点对之间的线段染黑,但必须保证线段不能在圆内相交。
旋转同构,问方案数,多组数据。
T
≤
1
0
5
,
n
≤
1
0
6
T\leq 10^5 ,n\leq10^6
T≤105,n≤106
题解
首先同构肯定是要考虑Burnside的,所以使用了Burnside后现在的问题变成:d个点不同构时的方案数(
d
∣
n
d|n
d∣n)。
但要注意到,如果
n
d
≥
2
\frac{n}{d}\geq 2
dn≥2,即循环节个数大于等于2个时的情况和
d
=
n
d=n
d=n,即只有一个循环时的情况是不一样的,要分开考虑。
d=n
d
=
n
d=n
d=n时相当是询问n个点不考虑同构时的方案数,由于此时最外围的n条边(i和i+1的边)对答案没有实质性影响,所以最后再乘以
2
n
2^n
2n,记为
f
n
f_n
fn为n个点只考虑内部连边时的方案数。
此时考虑0号点的连边情况:
①0号点没有连边
这种情况比较简单,因为0号点没有向其他点,所以把0号点删掉不影响答案,所以此时方案数为
2
∗
f
n
−
1
2*f_{n-1}
2∗fn−1,(*2是因为蓝色虚边可连可不连)。
②0号点有连边
考虑0号点连出去的最小标号为
i
(
1
<
i
<
n
−
1
i(1< i< n-1
i(1<i<n−1),则0-i这条边将整个图形化成了两边,而两边各为一个子问题,所以此时的方案数为
2
⋅
f
i
⋅
f
n
−
i
+
1
2\cdot f_{i}\cdot f_{n-i+1}
2⋅fi⋅fn−i+1(*2是因为红色实边可连可不连),但注意当i=2时并不需要*2,因为此时红色实边和虚边重合在一起了。.
综上所述,有
f
n
=
2
f
n
−
1
+
(
f
n
−
1
+
2
∑
i
=
3
n
−
2
f
i
⋅
f
n
−
i
+
1
)
(
n
≥
3
)
f_n=2f_{n-1}+\left(f_{n-1}+ 2\sum_{i=3}^{n-2}f_i\cdot f_{n-i+1}\right)\ \ (n\geq 3)
fn=2fn−1+(fn−1+2∑i=3n−2fi⋅fn−i+1) (n≥3),特别地有
f
1
=
f
2
=
1
f_1=f_2=1
f1=f2=1。
好那我们就可以开始大力FFT了
其实并不需要使用FFT,再推一下式子就可以了:
先整理一下:
f
n
=
2
f
n
−
1
+
2
∑
i
=
2
n
−
2
f
i
⋅
f
n
−
i
+
1
⇒
5
f
n
=
2
∑
i
=
1
n
f
i
⋅
f
n
−
i
+
1
−
f
n
−
1
f_n=2f_{n-1}+2\sum_{i=2}^{n-2}f_i\cdot f_{n-i+1}\Rightarrow 5f_n=2\sum_{i=1}^{n}f_i\cdot f_{n-i+1}-f_{n-1}
fn=2fn−1+2∑i=2n−2fi⋅fn−i+1⇒5fn=2∑i=1nfi⋅fn−i+1−fn−1
记
F
(
x
)
=
∑
n
=
0
∞
f
n
+
1
⋅
x
n
F(x)=\sum_{n=0}^\infty f_{n+1}\cdot x^n
F(x)=∑n=0∞fn+1⋅xn,则据上面的式子有
5
F
(
x
)
=
2
F
(
x
)
⋅
F
(
x
)
−
x
F
(
x
)
5F(x)=2F(x)\cdot F(x)-xF(x)
5F(x)=2F(x)⋅F(x)−xF(x)。
注意到
f
1
=
f
2
=
1
f_1=f_2=1
f1=f2=1,则有
5
F
(
x
)
=
2
F
(
x
)
⋅
F
(
x
)
−
x
F
(
x
)
+
2
x
+
3
5F(x)=2F(x)\cdot F(x)-xF(x)+2x+3
5F(x)=2F(x)⋅F(x)−xF(x)+2x+3。
把
F
(
x
)
F(x)
F(x)看成未知数,这是一个一元二次方程,解出可得
F
(
x
)
=
x
+
5
±
x
2
−
6
x
+
1
4
F(x)=\frac{x+5\pm\sqrt{x^2-6x+1}}{4}
F(x)=4x+5±x2−6x+1。
根据x=0时有
f
1
=
1
f_1=1
f1=1,所以
F
(
x
)
=
x
+
5
−
x
2
−
6
x
+
1
4
F(x)=\frac{x+5-\sqrt{x^2-6x+1}}{4}
F(x)=4x+5−x2−6x+1,则很容易就能算出
f
n
.
f_n.
fn.
循环节个数大于等于2时
首先有一点很清楚,相邻循环节是不可能相互连边的(除了两个端点外),否则就一定会出现边相交的情况。
之所以这个情况和上面的情况不一样,是因为我们并不知道0号点是处在某个循环节的哪个位置(一开始我自以为0号点就是循环节的开头,WA到怀疑人生)。
类似上面的处理,循环节周围的一圈边对答案没有本质性影响,最后再乘以
2
d
2^d
2d,记
g
d
g_d
gd为循环节长度为d,且不考虑外围边的方案数。
还是按0号点的连边情况分类:
①0号点没有连边
和上面类似,0号点没有连边就可以将他删掉,退化成d-1的情况,所以此时方案数为
2
∗
g
d
−
1
2*g_{d-1}
2∗gd−1
②0号点向右边[2,d)连边
假设0号点向右边连边的最小标号为
i
(
2
≤
i
<
d
)
i\ (2\leq i<d)
i (2≤i<d),则0-d及其对称边将整个图案划成了两个部分(如下图所示),红色框部分为子问题,蓝色框部分内部可以自由连边(即为
f
i
f_i
fi),所以此时方案数为
2
⋅
f
i
⋅
g
d
−
i
+
1
2\cdot f_i\cdot g_{d-i+1}
2⋅fi⋅gd−i+1(*2是因为蓝色实边可连可不连),但注意当i=2时并不需要*2,因为此时蓝色实边和虚边重合在一起了。.
③0号点没有向右边连边,但有向左边[2,d]连边
假设0号点向左边连边的最大标号为
i
(
2
≤
i
≤
d
)
i\ (2\leq i\leq d)
i (2≤i≤d),则0-d及其对称边将整个图案划成了两个部分(如下图所示),蓝色框部分为子问题,红色框部分内部可以自由连边(即为
f
i
+
1
f_{i+1}
fi+1),所以此时方案数为
2
⋅
f
i
+
1
⋅
g
d
−
i
2\cdot f_{i+1}\cdot g_{d-i}
2⋅fi+1⋅gd−i(*2是因为蓝色虚边可连可不连)
但这里有个边界情况挺坑的,就是当i=d时。
因为这里的条件是0号点没有向右边连边,即0号点的对称点(d号点)不能向左边连边,所以上图的红框部分应该修正为下图的橘框部分,即0不能包括d号点,此时方案数为
2
f
d
2f_d
2fd,(*2是因为橘色虚边可连可不连)
综上所述,有
g
d
=
2
∗
g
d
−
1
g_d=2*g_{d-1}
gd=2∗gd−1+
(
f
2
⋅
g
d
−
1
+
∑
i
=
3
d
−
1
2
⋅
f
i
⋅
g
d
−
i
+
1
)
\left( f_2\cdot g_{d-1}+\sum_{i=3}^{d-1}2\cdot f_i\cdot g_{d-i+1} \right)
(f2⋅gd−1+∑i=3d−12⋅fi⋅gd−i+1)+
(
2
⋅
f
d
+
∑
i
=
2
d
−
1
2
⋅
f
i
+
1
⋅
g
d
−
i
)
\left(2\cdot f_d+\sum_{i=2}^{d-1}2\cdot f_{i+1}\cdot g_{d-i} \right)
(2⋅fd+∑i=2d−12⋅fi+1⋅gd−i)
特别地有
g
1
=
1
,
g
2
=
3
g_1=1,g_2=3
g1=1,g2=3.
稍加整理后有: 5 ⋅ g d = 4 ∑ i = 1 d f i ⋅ g d − i + 1 − g d − 1 5\cdot g_d=4\sum_{i=1}^df_i\cdot g_{d-i+1}-g_{d-1} 5⋅gd=4∑i=1dfi⋅gd−i+1−gd−1
记
G
(
x
)
=
∑
n
=
0
∞
g
n
+
1
⋅
x
n
G(x)=\sum_{n=0}^\infty g_{n+1}\cdot x^n
G(x)=∑n=0∞gn+1⋅xn,则据上面的式子有
5
G
(
x
)
=
4
F
(
x
)
⋅
G
(
x
)
−
x
G
(
x
)
5G(x)=4F(x)\cdot G(x)-xG(x)
5G(x)=4F(x)⋅G(x)−xG(x)。
注意到
g
1
=
1
,
g
2
=
3
g_1=1,g_2=3
g1=1,g2=3,则有
5
G
(
x
)
=
4
F
(
x
)
⋅
G
(
x
)
−
x
G
(
x
)
+
1
5G(x)=4F(x)\cdot G(x)-xG(x)+1
5G(x)=4F(x)⋅G(x)−xG(x)+1。
把 G ( x ) G(x) G(x)看成未知数,可解得 G ( x ) = − 1 4 F ( x ) − x − 5 G(x)=-\frac{1}{4F(x)-x-5} G(x)=−4F(x)−x−51,带入 F ( x ) = x + 5 − x 2 − 6 x + 1 4 F(x)=\frac{x+5-\sqrt{x^2-6x+1}}{4} F(x)=4x+5−x2−6x+1后有, G ( x ) = 1 x 2 − 6 x + 1 G(x)=\frac{1}{\sqrt{x^2-6x+1}} G(x)=x2−6x+11,至此 g d g_d gd也出来了。
题外话
假设已知F(x)是一个m次多项式,即
F
(
x
)
=
∑
i
=
0
m
f
i
⋅
x
i
F(x)=\sum_{i=0}^{m}f_i\cdot x^i
F(x)=∑i=0mfi⋅xi,那么
G
(
x
)
=
F
k
(
x
)
G(x)=F^k(x)
G(x)=Fk(x)的麦克劳林展开式怎么求呢?
答:我会多项式快速幂!
问:那k不是整数呢?比如k=1/2.
答:我会FFT全家桶,先ln再exp!
问:又或者m很小呢?比如m=2,你还用FFT吗?
答:。。。
这里介绍一种特别的方法:
我们考虑对G(x)求导,则
G
′
(
x
)
=
[
F
k
(
x
)
]
′
=
k
F
k
−
1
(
x
)
⋅
F
′
(
x
)
G'(x)=[F^k(x)]'=kF^{k-1}(x)\cdot F'(x)
G′(x)=[Fk(x)]′=kFk−1(x)⋅F′(x);
两边乘以F(x):
F
(
x
)
G
′
(
x
)
=
k
F
k
(
x
)
⋅
F
′
(
x
)
F(x)G'(x)=kF^k(x)\cdot F'(x)
F(x)G′(x)=kFk(x)⋅F′(x);
注意到
G
(
k
)
=
F
k
(
x
)
G(k)=F^k(x)
G(k)=Fk(x):
F
(
x
)
⋅
G
′
(
x
)
=
k
G
(
x
)
⋅
F
′
(
x
)
F(x)\cdot G'(x)=kG(x)\cdot F'(x)
F(x)⋅G′(x)=kG(x)⋅F′(x).
所以我们现在有这样一条式子:
F
(
x
)
⋅
G
′
(
x
)
=
k
G
(
x
)
⋅
F
′
(
x
)
F(x)\cdot G'(x)=kG(x)\cdot F'(x)
F(x)⋅G′(x)=kG(x)⋅F′(x),感觉很对称有木有。
系数对齐一下就好了:
[
x
n
−
1
]
F
(
x
)
⋅
G
′
(
x
)
=
∑
i
=
0
m
f
i
⋅
(
n
−
i
)
g
n
−
i
[x^{n-1}]F(x)\cdot G'(x)=\sum_{i=0}^{m}f_i\cdot (n-i)g_{n-i}
[xn−1]F(x)⋅G′(x)=∑i=0mfi⋅(n−i)gn−i
[
x
n
−
1
]
k
G
(
x
)
⋅
F
′
(
x
)
=
k
∑
i
=
1
m
i
f
i
⋅
g
n
−
i
[x^{n-1}]kG(x)\cdot F'(x)=k\sum_{i=1}^{m}if_i\cdot g_{n-i}
[xn−1]kG(x)⋅F′(x)=k∑i=1mifi⋅gn−i
( F ′ ( x ) = ∑ i = 1 m i f i ⋅ x i − 1 , G ′ ( x ) = ∑ i = 1 ∞ i g i ⋅ x i − 1 ) \left(F'(x)=\sum_{i=1}^{m}if_i\cdot x^{i-1},G'(x)=\sum_{i=1}^{\infty}ig_i\cdot x^{i-1}\right) (F′(x)=∑i=1mifi⋅xi−1,G′(x)=∑i=1∞igi⋅xi−1)
两边系数相等,即
∑
i
=
0
m
f
i
⋅
(
n
−
i
)
g
n
−
i
=
k
∑
i
=
1
m
i
f
i
⋅
g
n
−
i
\sum_{i=0}^{m}f_i\cdot (n-i)g_{n-i}=k\sum_{i=1}^{m}if_i\cdot g_{n-i}
∑i=0mfi⋅(n−i)gn−i=k∑i=1mifi⋅gn−i;
整理一下:
n
f
0
g
n
=
k
∑
i
=
1
m
i
f
i
⋅
g
n
−
i
−
∑
i
=
1
m
f
i
⋅
(
n
−
i
)
g
n
−
i
nf_0g_n=k\sum_{i=1}^{m}if_i\cdot g_{n-i}-\sum_{i=1}^{m}f_i\cdot (n-i)g_{n-i}
nf0gn=k∑i=1mifi⋅gn−i−∑i=1mfi⋅(n−i)gn−i
即: g n = 1 f 0 ⋅ ( k + 1 n ∑ i = 1 m i f i ⋅ g n − i − ∑ i = 1 m f i ⋅ g n − i ) g_n=\frac{1}{f_0}\cdot \left(\frac{k+1}{n}\sum_{i=1}^{m}if_i\cdot g_{n-i}-\sum_{i=1}^{m}f_i\cdot g_{n-i} \right) gn=f01⋅(nk+1∑i=1mifi⋅gn−i−∑i=1mfi⋅gn−i)
代码
#include<bits/stdc++.h>
#define maxn 1000050
#define modu 1000000007
using namespace std;
typedef long long LL;
const LL inv6=(modu+1)/6;
LL pw2[maxn],pw6[maxn],pwi6[maxn];
LL I[maxn];
LL f[maxn],g[maxn];
LL h[maxn];//full convex,not iso
LL c1[maxn]={modu-2,13,modu-13,2},c2[maxn];
LL c[maxn]={1,3},cc[maxn];
//(2*x^3-13*x^2+13*x-2+sqrt(x^2-6*x+1)*(2*x^2-7*x))/(12*x-2)
LL dp[maxn];
LL t[maxn];
// LL f2[maxn]={1,2,3},g2[maxn]={5,modu-14,modu-23,modu-64};
//f: ((x+5-sqrt(x^2-6*x+1))/4)
//sqrt(x^2-6x+1) : g[i]=(6i-9)*g[i-1]+(3-i)*g[i-2] ,g0=1,g1=-3;
//f2: f^2
//2 4 16 72 502 3604
bool noprime[maxn];
int p[maxn],pnum;
LL phi[maxn];
void init() {
I[0]=I[1]=1;
f[0]=f[1]=1; g[0]=1,g[1]=modu-3;
h[0]=1,h[1]=h[2]=2;
}
void predo() {
phi[1]=1;
for (int i=2;i<maxn;++i) {
if (!noprime[i])
phi[i]=i-1,p[pnum++]=i;
for (int j=0;j<pnum&&i*p[j]<maxn;++j) {
noprime[i*p[j]]=1;
if (i%p[j])
phi[i*p[j]]=phi[i]*(p[j]-1);
else {
phi[i*p[j]]=phi[i]*p[j];
break;
}
}
}
}
void add(LL &a,LL b) {
a=(a+b)%modu;
}
int main() {
init();
predo();
for (int i=pw2[0]=1;i<maxn;++i) pw2[i]=pw2[i-1]*2%modu;
for (int i=pw6[0]=1;i<maxn;++i) pw6[i]=pw6[i-1]*6%modu;
for (int i=pwi6[0]=1;i<maxn;++i) pwi6[i]=pwi6[i-1]*inv6%modu;
for (int i=2;i<maxn;++i) I[i]=modu-modu/i*I[modu%i]%modu;
for (int i=2;i<maxn;++i) {
g[i]=(6*i-9+modu)*g[i-1]+(3-i+modu)*g[i-2];
g[i]%=modu;
g[i]=g[i]*I[i]%modu;
f[i]=(modu-g[i])*I[4]%modu;
}
for (int i=3;i<maxn;++i)
h[i]=f[i-1]*pw2[i]%modu;
for (int i=2;i<maxn;++i) {
c[i]=(6*i-3)*c[i-1]+(1-i)*c[i-2];
c[i]%=modu;
c[i]=(c[i]+modu)*I[i]%modu;
}
for (int i=1;i<maxn;++i)
cc[i]=c[i-1]*pw2[i]%modu;
for (int i=1;i<maxn;++i) {
add(dp[i],h[i]);
for (int j=i+i;j<maxn;j+=i)
add(dp[j],cc[i]*phi[j/i]);
dp[i]=dp[i]*I[i]%modu;
}
int T;
scanf("%d",&T);
while (T--) {
int n;
scanf("%d",&n);
if (n<maxn)
printf("%lld\n",dp[n]);
else
puts("0");
}
return 0;
}