Description
对于一个集合 T T T,定义 m i n d i f f ( T ) mindiff(T) mindiff(T)为 T T T中任意两元素差值最小值, m a x d i f f ( T ) maxdiff(T) maxdiff(T)为 T T T中任意两元素差值最大值,如果集合元素少于两个则定义两者值为 0 0 0. 对集合 { 1 , 2 , . . . , n } \{1,2,...,n\} {1,2,...,n}的所有子集 T T T的 m i n d i f f ( T ) ⋅ m a x d i f f ( T ) mindiff(T)\cdot maxdiff(T) mindiff(T)⋅maxdiff(T)求和
Input
一个整数 n ( 1 ≤ n ≤ 5 ⋅ 1 0 5 ) n(1\le n\le 5\cdot 10^5) n(1≤n≤5⋅105)
Output
输出答案,结果模 1 0 9 + 7 10^9+7 109+7
Sample Input
3
Sample Output
8
Solution
记
m
n
(
T
)
mn(T)
mn(T)为集合
T
T
T中任意两元素差值最小值,
m
x
(
T
)
mx(T)
mx(T)为集合
T
T
T中任意两元素差值最大值,对于集合
T
T
T,假设其
m
n
(
T
)
=
d
mn(T)=d
mn(T)=d,那么
m
x
(
T
)
mx(T)
mx(T)对答案的贡献是
d
d
d倍,进而考虑所有
m
n
(
S
)
≥
d
mn(S)\ge d
mn(S)≥d的集合
S
S
S的
m
x
mx
mx值之和,那么
m
x
(
T
)
mx(T)
mx(T)在
m
x
(
S
)
≥
1
,
.
.
.
,
d
mx(S)\ge 1,...,d
mx(S)≥1,...,d时都会被算一遍,也即算了
d
d
d遍,故答案为
∑
d
=
1
n
−
1
f
(
d
)
\sum\limits_{d=1}^{n-1}f(d)
d=1∑n−1f(d),其中
f
(
d
)
f(d)
f(d)为所有
m
n
(
S
)
≥
d
mn(S)\ge d
mn(S)≥d的集合
S
S
S的
m
x
mx
mx值之和,现在求
f
(
d
)
f(d)
f(d),枚举集合
T
T
T的元素个数
k
k
k和
m
x
(
T
)
=
t
mx(T)=t
mx(T)=t,那么在
1
1
1~
n
n
n中选出最小值和最大值使得两者差值为
t
t
t的方案数为
n
−
t
n-t
n−t种,而在两者之间的
t
−
1
t-1
t−1个位置中,为保证任意两个数字之间距离不小于
d
−
1
d-1
d−1,由插板法,提前拿出
(
k
−
1
)
(
d
−
1
)
(k-1)(d-1)
(k−1)(d−1)个位置空着,在剩余位置中选取
k
−
2
k-2
k−2个位置放剩下数字,故有
f
(
d
)
=
∑
k
=
2
n
∑
t
=
1
n
−
1
t
(
n
−
t
)
C
t
−
1
−
(
k
−
1
)
(
d
−
1
)
k
−
2
f(d)=\sum\limits_{k=2}^n\sum\limits_{t=1}^{n-1}t(n-t)C_{t-1-(k-1)(d-1)}^{k-2}
f(d)=k=2∑nt=1∑n−1t(n−t)Ct−1−(k−1)(d−1)k−2
注意到为使组合数合法,需要修改
k
,
d
k,d
k,d的下限,进而有
f
(
d
)
=
∑
(
k
−
1
)
d
≤
n
∑
t
=
(
k
−
1
)
d
n
−
1
t
(
n
−
t
)
C
t
−
1
−
(
k
−
1
)
(
d
−
1
)
k
−
2
f(d)=\sum\limits_{(k-1)d\le n}\sum\limits_{t=(k-1)d}^{n-1}t(n-t)C_{t-1-(k-1)(d-1)}^{k-2}
f(d)=(k−1)d≤n∑t=(k−1)d∑n−1t(n−t)Ct−1−(k−1)(d−1)k−2
由于满足
(
k
−
1
)
d
≤
n
(k-1)d\le n
(k−1)d≤n的
(
k
,
d
)
(k,d)
(k,d)组数只有
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)规模,只需快速求出
∑
t
=
(
k
−
1
)
d
n
−
1
t
(
n
−
t
)
C
t
−
1
−
(
k
−
1
)
(
d
−
1
)
k
−
2
\sum\limits_{t=(k-1)d}^{n-1}t(n-t)C_{t-1-(k-1)(d-1)}^{k-2}
t=(k−1)d∑n−1t(n−t)Ct−1−(k−1)(d−1)k−2
在
m
a
t
h
e
m
a
t
i
c
a
mathematica
mathematica里跑一下有
∑
t
=
(
k
−
1
)
d
n
−
1
t
(
n
−
t
)
C
t
−
1
−
(
k
−
1
)
(
d
−
1
)
k
−
2
=
(
n
−
1
+
2
d
)
(
n
−
(
k
−
1
)
d
)
(
n
−
(
k
−
1
)
(
d
−
1
)
)
k
(
k
+
1
)
C
n
−
1
−
(
k
−
1
)
(
d
−
1
)
k
−
2
\sum\limits_{t=(k-1)d}^{n-1}t(n-t)C_{t-1-(k-1)(d-1)}^{k-2}=\frac{(n-1+2d)(n-(k-1)d)(n-(k-1)(d-1))}{k(k+1)}C_{n-1-(k-1)(d-1)}^{k-2}
t=(k−1)d∑n−1t(n−t)Ct−1−(k−1)(d−1)k−2=k(k+1)(n−1+2d)(n−(k−1)d)(n−(k−1)(d−1))Cn−1−(k−1)(d−1)k−2
故可以
O
(
1
)
O(1)
O(1)求出该求和式,总时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
Code
#include<cstdio>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f,maxn=500005;
#define mod 1000000007
int inv[maxn],fact[maxn],sum[maxn];
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
void init(int n=500001)
{
inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
sum[0]=1;
for(int i=1;i<=n;i++)sum[i]=mul(sum[i-1],inv[i]);
fact[0]=1;
for(int i=1;i<=n;i++)fact[i]=mul(fact[i-1],i);
}
int C(int n,int m)
{
if(n<0||m<0||m>n)return 0;
return mul(fact[n],mul(sum[m],sum[n-m]));
}
int main()
{
init();
int n;
scanf("%d",&n);
int ans=0;
for(int d=1;d<=n-1;d++)
for(int k=2;(k-1)*d<=n&&k<=n;k++)
{
int w=n-(k-1)*(d-1);
int res=C(w-1,k-2);
res=mul(mul(res,n-1+2*d),mul(inv[k],inv[k+1]));
res=mul(res,mul(w-(k-1),w));
ans=add(ans,res);
}
printf("%d\n",ans);
return 0;
}