decription
对于一个有穷非空正整数集合 S = { x 1 , x 2 , x 3 , . . . , x n } ⊂ N + ( n ≥ 1 ) S=\{x_1,x_2,x_3,...,x_n\}\subset N^+(n\ge 1) S={x1,x2,x3,...,xn}⊂N+(n≥1),定义其和 s u m ( S ) sum(S) sum(S)为所有元素的和
- s u m ( S ) = x 1 + . . . + x n sum(S)=x_1+...+x_n sum(S)=x1+...+xn
定义其 m ( 1 ≤ m ≤ n ) m(1\le m\le n) m(1≤m≤n)阶子集集合 S m ( S ) \mathfrak{S}_m(S) Sm(S)为其所有 m m m阶子集的集合
- S m ( S ) = { T ∣ T = { y 1 , … , y m } ⊆ S } \mathfrak{S}_m(S)=\Big\{T\Big|T=\{y_1,\dots,y_m\}\subseteq S\Big\} Sm(S)={T∣∣∣T={y1,…,ym}⊆S}
T T T就是从 S S S中选 m m m个不同数的组成的一个子集, S m ( S ) \mathfrak{S}_m(S) Sm(S)就是子集 T T T所有情况的集合
定义其 k ( 1 ≤ k ≤ n ) k(1\le k\le n) k(1≤k≤n)级价值子集集 T k ( S ) \mathfrak{T}_k(S) Tk(S)为其所有 k k k阶子集中和整除 s u m ( S ) sum(S) sum(S)的
- T k ( S ) = { T ∣ k = s u m ( S ) s u m ( T ) ∧ k ∈ N + } ⋂ S k ( S ) \mathfrak{T}_k(S)=\Big\{T\Big|k=\frac{sum(S)}{sum(T)}\wedge k\in N^+\Big\}\bigcap\mathfrak{S}_k(S) Tk(S)={T∣∣∣k=sum(T)sum(S)∧k∈N+}⋂Sk(S)
就是满足上一个要求的基础上,子集元素和能整除原来的大集合的子集的集合
定义其 m ( 1 ≤ m ≤ n ) m(1\le m\le n) m(1≤m≤n)阶 k ( 1 ≤ k ≤ m ) k(1\le k\le m) k(1≤k≤m)级价值函数为其所有 m m m阶子集中 k k k级价值子集集的阶的最大值
- f m , k ( S ) = max { ∣ T k ( T ) ∣ ∣ T ∈ S m ( S ) } f_{m,k}(S)=\max\Big\{|\mathfrak{T}_{k}(T)|\quad\Big|\quad T\in\mathfrak{S}_m(S)\Big\} fm,k(S)=max{∣Tk(T)∣∣∣∣T∈Sm(S)}
定义其 m ( 1 ≤ m ≤ n ) m(1\le m\le n) m(1≤m≤n)阶 k ( 1 ≤ k ≤ m ) k(1\le k\le m) k(1≤k≤m)级价值函数的值点集合 P m , k ( S ) \mathfrak{P}_{m,k}(S) Pm,k(S)为取到上述最大值的 m m m阶子集的集合
- P m , k ( S ) = { T ∣ ∣ T k ( T ) ∣ = f m , k ( S ) } ⋂ S m ( S ) \mathfrak{P}_{m,k}(S)=\Big\{T\quad\Big|\quad |\mathfrak{T}_k(T)|=f_{m,k}(S)\Big\}\bigcap\mathfrak{S}_m(S) Pm,k(S)={T∣∣∣∣Tk(T)∣=fm,k(S)}⋂Sm(S)
给出 n , m , k n,m,k n,m,k,表示集合 S = 1 , 2 , . . . , n S={1,2,...,n} S=1,2,...,n
求 ∣ P m , k ( S ) ∣ |\mathfrak{P}_{m,k}(S)| ∣Pm,k(S)∣,即有多少个 m m m阶子集能取到最大值,答案对 1 0 9 + 7 10^9+7 109+7取模
1 ≤ n ≤ 1 0 12 1\le n\le 10^{12} 1≤n≤1012
子任务编号 | 分值 | m= | k= |
---|---|---|---|
1 | 10 | 1 | 1 |
2 | 10 | 2 | 1 |
3 | 10 | 2 | 2 |
4 | 10 | 3 | 1 |
5 | 10 | 3 | 2 |
6 | 10 | 3 | 3 |
7 | 10 | 4 | 1 |
8 | 10 | 4 | 2 |
9 | 10 | 4 | 3 |
10 | 10 | 4 | 4 |
solution
这种分数据点写不同算法的题真的很不错,如果不那么绕弯子就更好了!
有些点直接写吐了,giao
实际上,上面的四种定义,从后往前看其实很像递归的感觉,而我们就需要在这种递归思想中找到答案的规律!(证明也行)
倒着看,实际上是最开始的集合 S = { 1 , 2 , . . . , n } S=\{1,2,...,n\} S={1,2,...,n},从中选 m m m个定义为子集 T = { x 1 , . . . , x m } T=\{x_1,...,x_m\} T={x1,...,xm},再从 T T T中选 k k k个定义为子子集 P P P
m=k
显然只要从 S S S中选出 m m m个后, T T T中选 k k k个组成的 P P P,一定满足 s u m ( T ) = s u m ( P ) sum(T)=sum(P) sum(T)=sum(P)
所以答案就是从
n
n
n个中选
m
m
m个的方案数
C
(
n
,
m
)
C(n,m)
C(n,m)
void subtask1() {
int ans = 1;
for( int i = n;i > n - m;i -- )
ans = i % mod * ans % mod;
for( int i = 1;i <= m;i ++ )
ans = ans * qkpow( i, mod - 2 ) % mod;
printf( "%lld\n", ans );
}
m=2,k=1
不妨假设正整数 x 1 < x 2 x_1<x_2 x1<x2
由于 x 2 ∤ x 1 ⇒ x 2 ∤ ( x 1 + x 2 ) x_2\nmid x_1\Rightarrow x_2\nmid(x_1+x_2) x2∤x1⇒x2∤(x1+x2),(显然较大值不会是较小值的因数,不可能整除)
所以只可能有 x 1 ∣ x 2 ⇒ x 1 ∣ ( x 1 + x 2 ) x_1\mid x_2\Rightarrow x_1\mid(x_1+x_2) x1∣x2⇒x1∣(x1+x2)
枚举 x 1 = i x_1=i x1=i,则 x 2 = k ∗ i , k ∈ [ 2 , ⌊ n i ⌋ ] x_2=k*i,k\in[2,\lfloor\frac{n}{i}\rfloor] x2=k∗i,k∈[2,⌊in⌋],即有 ⌊ n i ⌋ − 2 + 1 = ⌊ n i ⌋ − 1 \lfloor\frac{n}{i}\rfloor-2+1=\lfloor\frac{n}{i}\rfloor-1 ⌊in⌋−2+1=⌊in⌋−1
答案为
∑
i
=
1
n
(
⌊
n
i
⌋
−
1
)
\sum_{i=1}^n(\lfloor\frac{n}{i}\rfloor-1)
i=1∑n(⌊in⌋−1)
按照
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋分块,连续一段区间
[
l
,
r
]
[l,r]
[l,r]的
⌊
n
i
⌋
\lfloor\frac{n}{i}\rfloor
⌊in⌋相同
void subtask2() {
int ans = 0;
for( int r = n, l;r > 0;r = l - 1 ) {
if( r == 1 ) break;
l = n / ( n / r + 1 ) + 1;
int t = n / r;
ans = ( ans + t % mod * ( r - l + 1 ) % mod ) % mod;
}
printf( "%lld\n", ans );
}
m=3,k=1
假设
n
n
n足够大且存在
x
1
<
x
2
<
x
3
x_1<x_2<x_3
x1<x2<x3满足
{
x
1
∣
(
x
1
+
x
2
+
x
3
)
x
2
∣
(
x
1
+
x
2
+
x
3
)
x
3
∣
(
x
1
+
x
2
+
x
3
)
\begin{cases} x_1\mid (x_1+x_2+x_3)\\ x_2\mid (x_1+x_2+x_3)\\ x_3\mid (x_1+x_2+x_3) \end{cases}
⎩⎪⎨⎪⎧x1∣(x1+x2+x3)x2∣(x1+x2+x3)x3∣(x1+x2+x3)
不失一般性假设正整数
1
<
x
<
y
<
z
1<x<y<z
1<x<y<z,即
1
>
1
x
>
1
y
>
1
z
1>\frac{1}{x}>\frac{1}{y}>\frac{1}{z}
1>x1>y1>z1
满足
{
z
∗
x
1
=
x
1
+
x
2
+
x
3
y
∗
x
2
=
x
1
+
x
2
+
x
3
x
∗
x
3
=
x
1
+
x
2
+
x
3
⇒
{
x
1
x
1
+
x
2
+
x
3
=
1
z
x
2
x
1
+
x
2
+
x
3
=
1
y
x
3
x
1
+
x
2
+
x
3
=
1
x
\begin{cases} z*x_1 = x_1+x_2+x_3\\ y*x_2 = x_1+x_2+x_3\\ x*x_3 = x_1+x_2+x_3 \end{cases}\\ \Rightarrow \begin{cases} \frac{x_1}{x_1+x_2+x_3}=\frac{1}{z}\\ \frac{x_2}{x_1+x_2+x_3}=\frac{1}{y}\\ \frac{x_3}{x_1+x_2+x_3}=\frac{1}{x}\\ \end{cases}
⎩⎪⎨⎪⎧z∗x1=x1+x2+x3y∗x2=x1+x2+x3x∗x3=x1+x2+x3⇒⎩⎪⎨⎪⎧x1+x2+x3x1=z1x1+x2+x3x2=y1x1+x2+x3x3=x1
则有
1
x
+
1
y
+
1
z
=
1
\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=1
x1+y1+z1=1,且
1
=
1
x
+
1
y
+
1
z
<
3
x
⇒
x
<
3
⇒
x
=
2
1=\frac{1}{x}+\frac{1}{y}+\frac{1}{z}<\frac{3}{x}\Rightarrow x<3\Rightarrow x=2
1=x1+y1+z1<x3⇒x<3⇒x=2
因此 1 y + 1 z = 1 2 = y + z y z ⇒ 2 ( y + z ) − y z = 0 ⇒ ( y − 2 ) ( z − 2 ) = 4 \frac{1}{y}+\frac{1}{z}=\frac{1}{2}=\frac{y+z}{yz}\Rightarrow 2(y+z)-yz=0\Rightarrow (y-2)(z-2)=4 y1+z1=21=yzy+z⇒2(y+z)−yz=0⇒(y−2)(z−2)=4
从而解出了唯一解 x = 2 , y = 3 , z = 6 x=2,y=3,z=6 x=2,y=3,z=6
于是,有
{
6
∗
x
1
=
x
1
+
x
2
+
x
3
3
∗
x
2
=
x
1
+
x
2
+
x
3
2
∗
x
3
=
x
1
+
x
2
+
x
3
⇒
6
x
1
=
3
x
2
=
2
x
3
\begin{cases} 6*x_1 = x_1+x_2+x_3\\ 3*x_2 = x_1+x_2+x_3\\ 2*x_3 = x_1+x_2+x_3 \end{cases}\\ \Rightarrow 6x_1=3x_2=2x_3
⎩⎪⎨⎪⎧6∗x1=x1+x2+x33∗x2=x1+x2+x32∗x3=x1+x2+x3⇒6x1=3x2=2x3
令
k
=
x
1
⇒
x
2
=
2
k
,
x
3
=
3
k
k=x_1\Rightarrow x_2=2k,x_3=3k
k=x1⇒x2=2k,x3=3k
所以 ( x 1 , x 2 , x 3 ) = ( k , 2 k , 3 k ) , k ∈ N + (x_1,x_2,x_3)=(k,2k,3k),k\in N^+ (x1,x2,x3)=(k,2k,3k),k∈N+,在 n ≥ 3 n\ge 3 n≥3时存在
要满足 x 1 , x 2 , x 3 ≤ n x_1,x_2,x_3\le n x1,x2,x3≤n,所以 k k k的取值范围为 [ 1 , ⌊ n 3 ⌋ ] [1,\lfloor\frac{n}{3}\rfloor] [1,⌊3n⌋]
答案为 ⌊ n 3 ⌋ \lfloor\frac{n}{3}\rfloor ⌊3n⌋
void subtask3() {
printf( "%lld\n", ( n / 3 ) % mod );
}
m=3,k=2
不妨假设正整数 x 1 < x 2 < x 3 x_1<x_2<x_3 x1<x2<x3
因为
{
(
x
1
+
x
3
)
∤
x
2
⇒
(
x
1
+
x
3
)
∤
(
x
1
+
x
2
+
x
3
)
(
x
2
+
x
3
)
∤
x
1
⇒
(
x
2
+
x
3
)
∤
(
x
1
+
x
2
+
x
3
)
\begin{cases} (x_1+x_3)\nmid x_2\Rightarrow (x_1+x_3)\nmid(x_1+x_2+x_3)\\ (x_2+x_3)\nmid x_1\Rightarrow (x_2+x_3)\nmid(x_1+x_2+x_3) \end{cases}
{(x1+x3)∤x2⇒(x1+x3)∤(x1+x2+x3)(x2+x3)∤x1⇒(x2+x3)∤(x1+x2+x3)
所以只可能有
(
x
1
+
x
2
)
∣
x
3
⇒
(
x
1
+
x
2
)
∣
(
x
1
+
x
2
+
x
3
)
(x_1+x_2)\mid x_3\Rightarrow (x_1+x_2)\mid(x_1+x_2+x_3)
(x1+x2)∣x3⇒(x1+x2)∣(x1+x2+x3)
尝试枚举
x
1
+
x
2
=
i
x_1+x_2=i
x1+x2=i,得到
x
3
x_3
x3的取值个数(与m=2,k-1
的求法一样)
再求出 i i i拆分成 x 1 + x 2 x_1+x_2 x1+x2的拆分方案,利用乘法原理求得最后答案
枚举 x 1 x_1 x1后(实际上不可能在代码里枚举)便可唯一确定 x 2 x_2 x2的取值
对于和为 i i i而言:如果 x 1 = i − 1 x_1=i-1 x1=i−1,则 x 2 = 1 x_2=1 x2=1; … \dots … ;如果 x 1 = 1 x_1=1 x1=1,则 x 2 = i − 1 x_2=i-1 x2=i−1,一定有 i − 1 i-1 i−1种拆分方法
但是集合 { 2 , 3 } \{2,3\} {2,3}和集合 { 3 , 2 } \{3,2\} {3,2}是没有区别的,所以形如 a + b a+b a+b的拆分被算了两次,且不合法的形如 a + a a+a a+a的拆分也被算了一次
先减去不合法的 a + a a+a a+a形式拆分(如果存在的话,显然这种拆分存在当且仅当 i i i为偶数)
再除以二就是 a + b a+b a+b形式的拆分个数了
同样的,我们需要分块来做
答案为 ∑ i = 1 n ⌊ n i ⌋ i − 1 − [ 2 ∣ i ] 2 \sum_{i=1}^n\lfloor\frac{n}{i}\rfloor\frac{i-1-[2|i]}{2} i=1∑n⌊in⌋2i−1−[2∣i]
void subtask6() {
/*
(i-1-[2|i])/2
通过打表发现
1->0
2->0
3->1
4->1
...
所以如果是奇数 就是/2
如果是偶数 那么就是/2-1
相当于是两组等差数列
注意l开局的奇偶即可
*/
int ans = 0;
for( int l = 1, r;l <= n;l = r + 1 ) {
r = n / ( n / l );
int c = 0;
//x首相 y项数 因为有两组所以不用/2了
if( l & 1 ) {
int len = r - l + 1;
int x = l / 2 % mod;
int y = len / 2 % mod;
c = ( c + ( x + x + y - 1 ) % mod * y % mod ) % mod;
if( len & 1 ) c = ( c + r / 2 ) % mod;
}
else {
int x = l / 2 - 1;
c = ( c + x % mod ) % mod;
int len = r - l;
int y = len / 2 % mod;
x ++;
c = ( c + ( x + x + y - 1 ) % mod * y % mod ) % mod;
if( len & 1 ) c = ( c + r / 2 ) % mod;
}
ans = ( ans + n / r % mod * c % mod ) % mod;
}
printf( "%lld\n", ( ans + mod ) % mod );
}
m=4,k=1
假设
n
n
n足够大且存在
x
1
<
x
2
<
x
3
<
x
4
→
1
>
1
x
1
>
1
x
2
>
1
x
3
>
1
x
4
x_1<x_2<x_3<x_4\rightarrow 1>\frac{1}{x_1}>\frac{1}{x_2}>\frac{1}{x_3}>\frac{1}{x_4}
x1<x2<x3<x4→1>x11>x21>x31>x41,满足
{
x
1
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
x
2
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
x
3
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
x
4
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
\begin{cases} x_1|(x_1+x_2+x_3+x_4)\\ x_2|(x_1+x_2+x_3+x_4)\\ x_3|(x_1+x_2+x_3+x_4)\\ x_4|(x_1+x_2+x_3+x_4) \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x1∣(x1+x2+x3+x4)x2∣(x1+x2+x3+x4)x3∣(x1+x2+x3+x4)x4∣(x1+x2+x3+x4)
不失一般性地假设
x
<
y
<
z
<
w
x<y<z<w
x<y<z<w,满足
{
x
1
+
x
2
+
x
3
+
x
4
=
w
∗
x
1
x
1
+
x
2
+
x
3
+
x
4
=
z
∗
x
2
x
1
+
x
2
+
x
3
+
x
4
=
y
∗
x
3
x
1
+
x
2
+
x
3
+
x
4
=
x
∗
x
4
\begin{cases} x_1+x_2+x_3+x_4=w*x_1\\ x_1+x_2+x_3+x_4=z*x_2\\ x_1+x_2+x_3+x_4=y*x_3\\ x_1+x_2+x_3+x_4=x*x_4 \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x1+x2+x3+x4=w∗x1x1+x2+x3+x4=z∗x2x1+x2+x3+x4=y∗x3x1+x2+x3+x4=x∗x4
则,有
1
x
1
+
1
x
2
+
1
x
3
+
1
x
4
=
1
\frac{1}{x_1}+\frac{1}{x_2}+\frac{1}{x_3}+\frac{1}{x_4}=1
x11+x21+x31+x41=1
假设 x ≥ 3 x\ge 3 x≥3,则 1 x 1 + 1 x 2 + 1 x 3 + 1 x 4 ≤ 1 3 + 1 4 + 1 5 + 1 6 < 1 \frac{1}{x_1}+\frac{1}{x_2}+\frac{1}{x_3}+\frac{1}{x_4}\le \frac{1}{3}+\frac{1}{4}+\frac{1}{5}+\frac{1}{6}<1 x11+x21+x31+x41≤31+41+51+61<1
假设矛盾,所以 1 < x < 3 ⇒ x = 2 1<x<3\Rightarrow x=2 1<x<3⇒x=2
假设 y ≥ 6 y\ge 6 y≥6,则 1 x 2 + 1 x 3 + 1 x 4 ≤ 1 6 + 1 7 + 1 8 < 1 2 \frac{1}{x_2}+\frac{1}{x_3}+\frac{1}{x_4}\le \frac{1}{6}+\frac{1}{7}+\frac{1}{8}<\frac{1}{2} x21+x31+x41≤61+71+81<21
假设矛盾,所以 2 < y < 6 ⇒ y = 2 / 3 / 4 2<y<6\Rightarrow y=2/3/4 2<y<6⇒y=2/3/4
- y = 3 y=3 y=3,有 ( z − 6 ) ( w − 6 ) = 36 → ( 2 , 3 , 7 , 42 ) ; ( 2 , 3 , 8 , 24 ) ; ( 2 , 3 , 9 , 18 ) ; ( 2 , 3 , 10 , 15 ) (z-6)(w-6)=36\rightarrow (2,3,7,42);(2,3,8,24);(2,3,9,18);(2,3,10,15) (z−6)(w−6)=36→(2,3,7,42);(2,3,8,24);(2,3,9,18);(2,3,10,15)
- y = 4 y=4 y=4,有 ( z − 4 ) ( w − 4 ) = 16 → ( 2 , 3 , 5 , 20 ) ; ( 2 , 4 , 6 , 12 ) (z-4)(w-4)=16\rightarrow(2,3,5,20);(2,4,6,12) (z−4)(w−4)=16→(2,3,5,20);(2,4,6,12)
- y = 5 y=5 y=5,有 ( 3 z − 10 ) ( 3 w − 10 ) = 100 → ∅ (3z-10)(3w-10)=100\rightarrow \empty (3z−10)(3w−10)=100→∅
所以整理一下,结果为
( x 1 , x 2 , x 3 , x 4 ) = ( k , 2 k , 3 k , 6 k ) ; ; ( k , 2 k , 6 k , 9 k ) ; ; ( k , 3 k , 8 k , 12 k ) ; ; ( k , 4 k , 5 k , 10 k ) ; ; ( k , 6 k , 14 k , 21 k ) ; ; ( 2 k , 3 k , 10 k , 15 k ) (x_1,x_2,x_3,x_4)=(k,2k,3k,6k);;(k,2k,6k,9k);;(k,3k,8k,12k);;(k,4k,5k,10k);;(k,6k,14k,21k);;(2k,3k,10k,15k) (x1,x2,x3,x4)=(k,2k,3k,6k);;(k,2k,6k,9k);;(k,3k,8k,12k);;(k,4k,5k,10k);;(k,6k,14k,21k);;(2k,3k,10k,15k)
(反解过程,上面有示范,这里不再展开计算)
所以在 n ≥ 6 n\ge 6 n≥6的时候才会全都成立,当 n = 4 / 5 n=4/5 n=4/5就手玩硬算
答案为
{
1
n
=
4
,
5
⌊
n
6
⌋
+
⌊
n
9
⌋
+
⌊
n
10
⌋
+
⌊
n
12
⌋
+
⌊
n
15
⌋
+
⌊
n
21
⌋
n
≥
6
\begin{cases} 1\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\ n=4,5\\ \lfloor\frac{n}{6}\rfloor+\lfloor\frac{n}{9}\rfloor+\lfloor\frac{n}{10}\rfloor+\lfloor\frac{n}{12}\rfloor+\lfloor\frac{n}{15}\rfloor+\lfloor\frac{n}{21}\rfloor\quad n\ge 6 \end{cases}
{1 n=4,5⌊6n⌋+⌊9n⌋+⌊10n⌋+⌊12n⌋+⌊15n⌋+⌊21n⌋n≥6
void subtask4() {
if( n == 4 or n == 5 ) printf( "1\n" );
else printf( "%lld\n", ( n / 6 % mod + n / 9 % mod + n / 10 % mod + n / 12 % mod + n / 15 % mod + n / 21 % mod ) % mod );
}
m=4,k=2
不妨假设正整数
x
1
<
x
2
<
x
3
<
x
4
x_1<x_2<x_3<x_4
x1<x2<x3<x4,则有
{
(
x
2
+
x
4
)
∤
(
x
1
+
x
3
)
⇒
(
x
2
+
x
4
)
∤
(
x
1
+
x
2
+
x
3
+
x
4
)
(
x
3
+
x
4
)
∤
(
x
1
+
x
2
)
⇒
(
x
3
+
x
4
)
∤
(
x
1
+
x
2
+
x
3
+
x
4
)
\begin{cases} (x_2+x_4)\nmid(x_1+x_3)\Rightarrow (x_2+x_4)\nmid(x_1+x_2+x_3+x_4)\\ (x_3+x_4)\nmid(x_1+x_2)\Rightarrow (x_3+x_4)\nmid(x_1+x_2+x_3+x_4) \end{cases}
{(x2+x4)∤(x1+x3)⇒(x2+x4)∤(x1+x2+x3+x4)(x3+x4)∤(x1+x2)⇒(x3+x4)∤(x1+x2+x3+x4)
假设
n
n
n足够大且存在
x
1
<
x
2
<
x
3
<
x
4
x_1<x_2<x_3<x_4
x1<x2<x3<x4,满足
{
(
x
1
+
x
2
)
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
⇒
(
x
1
+
x
2
)
∣
(
x
3
+
x
4
)
(
x
1
+
x
3
)
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
⇒
(
x
1
+
x
3
)
∣
(
x
2
+
x
4
)
(
x
1
+
x
4
)
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
⇒
x
1
+
x
4
=
x
2
+
x
3
(
x
2
+
x
3
)
∣
(
x
1
+
x
2
+
x
3
+
x
4
)
⇒
x
1
+
x
4
=
x
2
+
x
3
\begin{cases} (x_1+x_2)\mid(x_1+x_2+x_3+x_4)\Rightarrow (x_1+x_2)\mid (x_3+x_4)\\ (x_1+x_3)\mid(x_1+x_2+x_3+x_4)\Rightarrow (x_1+x_3)\mid (x_2+x_4)\\ (x_1+x_4)\mid(x_1+x_2+x_3+x_4)\Rightarrow x_1+x_4=x_2+x_3\\ (x_2+x_3)\mid(x_1+x_2+x_3+x_4)\Rightarrow x_1+x_4=x_2+x_3\\ \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧(x1+x2)∣(x1+x2+x3+x4)⇒(x1+x2)∣(x3+x4)(x1+x3)∣(x1+x2+x3+x4)⇒(x1+x3)∣(x2+x4)(x1+x4)∣(x1+x2+x3+x4)⇒x1+x4=x2+x3(x2+x3)∣(x1+x2+x3+x4)⇒x1+x4=x2+x3
因为
x
2
<
x
3
<
x
4
x_2<x_3<x_4
x2<x3<x4,所以
x
2
+
x
4
x_2+x_4
x2+x4不可能大于等于
x
4
x_4
x4的三倍,只能是
x
4
x_4
x4的两倍多(毕竟
x
4
x_4
x4要
+
x
1
+x_1
+x1)
设 s ( x 1 + x 3 ) = x 2 + x 4 = 2 x 2 + x 3 − x 1 < 3 ( x 1 + x 3 ) s(x_1+x_3)=x_2+x_4=2x_2+x_3-x_1<3(x_1+x_3) s(x1+x3)=x2+x4=2x2+x3−x1<3(x1+x3)
所以 1 < s < 3 ⇒ s = 2 1<s<3\Rightarrow s=2 1<s<3⇒s=2
设 t ( x 1 + x 2 ) = x 3 + x 4 = 5 x 2 − 7 x 1 < 5 ( x 1 + x 2 ) t(x_1+x_2)=x_3+x_4=5x_2-7x_1<5(x_1+x_2) t(x1+x2)=x3+x4=5x2−7x1<5(x1+x2)
所以 2 = s < t < 5 ⇒ t = 3 / 4 2=s<t<5\Rightarrow t=3/4 2=s<t<5⇒t=3/4
推出 ( x 1 , x 2 , x 3 , x 4 ) = ( k , 5 k , 7 k , 11 k ) ; ; ( k , 11 k , 19 k , 20 k ) (x_1,x_2,x_3,x_4)=(k,5k,7k,11k);;(k,11k,19k,20k) (x1,x2,x3,x4)=(k,5k,7k,11k);;(k,11k,19k,20k)
在
n
≥
11
n\ge 11
n≥11时,满足假设条件,
n
<
11
n<11
n<11的情况直接手玩
{
1
n
=
4
,
5
,
6
3
n
=
7
6
n
=
8
9
n
=
9
10
n
=
10
⌊
n
11
⌋
+
⌊
n
29
n
≥
11
\begin{cases} 1\quad\quad\quad\quad\quad\ n=4,5,6\\ 3\quad\quad\quad\quad\quad\ n=7\\ 6\quad\quad\quad\quad\quad\ n=8\\ 9\quad\quad\quad\quad\quad\ n=9\\ 10\quad\quad\quad\quad\ \ \ n=10\\ \lfloor\frac{n}{11}\rfloor+\lfloor\frac{n}{29}\quad n\ge 11 \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧1 n=4,5,63 n=76 n=89 n=910 n=10⌊11n⌋+⌊29nn≥11
void subtask5() {
if( n == 4 or n == 5 or n == 6 ) printf( "1\n" );
else if( n == 7 ) printf( "3\n" );
else if( n == 8 ) printf( "6\n" );
else if( n == 9 ) printf( "9\n" );
else if( n == 10 ) printf( "10\n" );
else printf( "%lld\n", ( n / 11 % mod + n / 29 % mod ) % mod );
}
m=4,k=3
不妨假设正整数
x
1
<
x
2
<
x
3
<
x
4
x_1<x_2<x_3<x_4
x1<x2<x3<x4,有
{
(
x
1
+
x
2
+
x
4
)
∤
x
3
⇒
(
x
1
+
x
2
+
x
4
)
∤
(
x
1
+
x
2
+
x
3
+
x
4
)
(
x
1
+
x
3
+
x
4
)
∤
x
2
⇒
(
x
1
+
x
3
+
x
4
)
∤
(
x
1
+
x
2
+
x
3
+
x
4
)
(
x
3
+
x
2
+
x
4
)
∤
x
1
⇒
(
x
3
+
x
2
+
x
4
)
∤
(
x
1
+
x
2
+
x
3
+
x
4
)
\begin{cases} (x_1+x_2+x_4)\nmid x_3\Rightarrow (x_1+x_2+x_4)\nmid(x_1+x_2+x_3+x_4)\\ (x_1+x_3+x_4)\nmid x_2\Rightarrow (x_1+x_3+x_4)\nmid(x_1+x_2+x_3+x_4)\\ (x_3+x_2+x_4)\nmid x_1\Rightarrow (x_3+x_2+x_4)\nmid(x_1+x_2+x_3+x_4)\\ \end{cases}
⎩⎪⎨⎪⎧(x1+x2+x4)∤x3⇒(x1+x2+x4)∤(x1+x2+x3+x4)(x1+x3+x4)∤x2⇒(x1+x3+x4)∤(x1+x2+x3+x4)(x3+x2+x4)∤x1⇒(x3+x2+x4)∤(x1+x2+x3+x4)
所以只可能有
( x 1 + x 2 + x 3 ) ∣ x 4 ⇒ ( x 1 + x 2 + x 3 ) ∣ ( x 1 + x 2 + x 3 + x 4 ) (x_1+x_2+x_3)\mid x_4\Rightarrow (x_1+x_2+x_3)\mid(x_1+x_2+x_3+x_4) (x1+x2+x3)∣x4⇒(x1+x2+x3)∣(x1+x2+x3+x4)
通过枚举 i = x 1 + x 2 + x 3 i=x_1+x_2+x_3 i=x1+x2+x3,确定 x 4 x_4 x4的个数 n − i n-i n−i,再计算 i i i拆分的方案,乘法原理即可求得最后答案
考虑计算拆分方案:假想枚举 x 1 x_1 x1,则 a + b + c a+b+c a+b+c的形式会被计算 6 6 6次, a + a + b a+a+b a+a+b的形式会被计算 3 3 3次, a + a + a a+a+a a+a+a的形式会被计算 1 1 1次
当 x 1 = 1 , 2 , . . . i − 2 x_1=1,2,...i-2 x1=1,2,...i−2,则 x 2 = [ 1 , i − 2 ] , . . . , [ 1 , 1 ] x_2=[1,i-2],...,[1,1] x2=[1,i−2],...,[1,1]
所以方案数为 ( i − 2 ) + ( i − 1 ) + . . . + 1 = ( i − 1 ) ( i − 2 ) 2 (i-2)+(i-1)+...+1=\frac{(i-1)(i-2)}{2} (i−2)+(i−1)+...+1=2(i−1)(i−2)
我们如果能减去这些不合法的形式,再除以六就是拆分的最终方案数了
显然, a + a + b a+a+b a+a+b的形式能被计算到,当且仅当 a ∈ [ 1 , ⌊ i − 1 2 ⌋ ] a\in [1,\lfloor\frac{i-1}{2}\rfloor] a∈[1,⌊2i−1⌋]。 a + a + a a+a+a a+a+a的形式能被计算到,当且仅当 i = 3 a i=3a i=3a
我们可以再假想枚举 x 2 x_2 x2,来减掉 a + a + b a+a+b a+a+b的形式, 即 − 3 ⌊ i − 1 2 ⌋ -3\lfloor\frac{i-1}{2}\rfloor −3⌊2i−1⌋,将这个暴力拆开与上面的合并,则会发现 i i i为偶数的时候,多减了 3 2 \frac{3}{2} 23,要加回来
但这样 a + a + a a+a+a a+a+a形式就会被减去三次,多减了两次,需要加回来 2 [ 3 ∣ i ] 2[3|i] 2[3∣i](别忘了这个形式存在的前提是 i = 3 a i=3a i=3a),这个的基础是最后总数 / 6 /6 /6,但是答案的表示是 / 12 /12 /12
所以上面分子写的是 4 4 4的系数
所以答案是
{
1
n
=
4
5
n
=
5
∑
i
=
1
n
⌊
n
i
⌋
i
2
−
6
i
+
5
+
3
[
2
∣
i
]
+
4
[
3
∣
i
]
12
n
≥
6
\begin{cases} 1\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\ \ \ n=4\\ 5\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\ \ \ n=5\\ \sum_{i=1}^n\lfloor\frac{n}{i}\rfloor\frac{i^2-6i+5+3[2|i]+4[3|i]}{12}\quad n\ge 6 \end{cases}
⎩⎪⎨⎪⎧1 n=45 n=5∑i=1n⌊in⌋12i2−6i+5+3[2∣i]+4[3∣i]n≥6
但是又因为涉及分块,所以计算一段区间内
2
,
3
2,3
2,3的倍数个数,简直要命,主要是左端点开头,救命!!
void subtask7() {
if( n == 4 ) printf( "1\n" );
else if( n == 5 ) printf( "5" );
else {
int ans = 0, lst = 0, inv2 = qkpow( 2, mod - 2 ), inv3 = qkpow( 3, mod - 2 ), inv12 = qkpow( 12, mod - 2 );
for( int l = 1, r;l <= n;l = r + 1 ) {
r = ( n / ( n / l ) );
int len = r - l + 1;
int now = r % mod * ( ( r + 1 ) % mod ) % mod * ( ( r % mod * 2 + 1 ) % mod ) % mod * inv2 % mod * inv3 % mod;
int c = ( now - lst + mod ) % mod;
c = ( c - ( l % mod + r % mod ) % mod * ( len % mod ) % mod * inv2 % mod * 6 % mod + mod ) % mod;
c = ( c + len % mod * 5 % mod + mod ) % mod;
lst = now;
c = ( c + ( len / 2 % mod + ( len & 1 and ! ( l & 1 ) ) ) * 3 % mod ) % mod;
c = ( c + ( len / 3 % mod + ( ( len % 3 != 0 ) and ( ( l % 3 == 0 ) or ( len % 3 == 2 and l % 3 == 2 ) ) ) ) * 4 % mod ) % mod;
c = c * inv12 % mod;
ans = ( ans + n / r % mod * c % mod ) % mod;
}
printf( "%lld\n", ans );
}
}
code
#include <cstdio>
#include <cmath>
using namespace std;
#define mod 1000000007
#define int long long
int n, m, k;
int qkpow( int x, int y ) {
int ans = 1;
while( y ) {
if( y & 1 ) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
void subtask1() {
int ans = 1;
for( int i = n;i > n - m;i -- )
ans = i % mod * ans % mod;
for( int i = 1;i <= m;i ++ )
ans = ans * qkpow( i, mod - 2 ) % mod;
printf( "%lld\n", ans );
}
void subtask2() {
int ans = 0;
for( int r = n, l;r > 0;r = l - 1 ) {
if( r == 1 ) break;
l = n / ( n / r + 1 ) + 1;
int t = n / r;
ans = ( ans + t % mod * ( r - l + 1 ) % mod ) % mod;
}
printf( "%lld\n", ans );
}
void subtask3() {
printf( "%lld\n", ( n / 3 ) % mod );
}
void subtask4() {
if( n == 4 or n == 5 ) printf( "1\n" );
else printf( "%lld\n", ( n / 6 % mod + n / 9 % mod + n / 10 % mod + n / 12 % mod + n / 15 % mod + n / 21 % mod ) % mod );
}
void subtask5() {
if( n == 4 or n == 5 or n == 6 ) printf( "1\n" );
else if( n == 7 ) printf( "3\n" );
else if( n == 8 ) printf( "6\n" );
else if( n == 9 ) printf( "9\n" );
else if( n == 10 ) printf( "10\n" );
else printf( "%lld\n", ( n / 11 % mod + n / 29 % mod ) % mod );
}
void subtask6() {
int ans = 0;
for( int l = 1, r;l <= n;l = r + 1 ) {
r = n / ( n / l );
int c = 0;
if( l & 1 ) {
int len = r - l + 1;
int x = l / 2 % mod;
int y = len / 2 % mod;
c = ( c + ( x + x + y - 1 ) % mod * y % mod ) % mod;
if( len & 1 ) c = ( c + r / 2 ) % mod;
}
else {
int x = l / 2 - 1;
c = ( c + x % mod ) % mod;
int len = r - l;
int y = len / 2 % mod;
x ++;
c = ( c + ( x + x + y - 1 ) % mod * y % mod ) % mod;
if( len & 1 ) c = ( c + r / 2 ) % mod;
}
ans = ( ans + n / r % mod * c % mod ) % mod;
}
printf( "%lld\n", ( ans + mod ) % mod );
}
void subtask7() {
if( n == 4 ) printf( "1\n" );
else if( n == 5 ) printf( "5" );
else {
int ans = 0, lst = 0, inv2 = qkpow( 2, mod - 2 ), inv3 = qkpow( 3, mod - 2 ), inv12 = qkpow( 12, mod - 2 );
for( int l = 1, r;l <= n;l = r + 1 ) {
r = ( n / ( n / l ) );
int len = r - l + 1;
int now = r % mod * ( ( r + 1 ) % mod ) % mod * ( ( r % mod * 2 + 1 ) % mod ) % mod * inv2 % mod * inv3 % mod;
int c = ( now - lst + mod ) % mod;
c = ( c - ( l % mod + r % mod ) % mod * ( len % mod ) % mod * inv2 % mod * 6 % mod + mod ) % mod;
c = ( c + len % mod * 5 % mod + mod ) % mod;
lst = now;
c = ( c + ( len / 2 % mod + ( len & 1 and ! ( l & 1 ) ) ) * 3 % mod ) % mod;
c = ( c + ( len / 3 % mod + ( ( len % 3 != 0 ) and ( ( l % 3 == 0 ) or ( len % 3 == 2 and l % 3 == 2 ) ) ) ) * 4 % mod ) % mod;
c = c * inv12 % mod;
ans = ( ans + n / r % mod * c % mod ) % mod;
}
printf( "%lld\n", ans );
}
}
signed main() {
freopen( "vegetable.in", "r", stdin );
freopen( "vegetable.out", "w", stdout );
scanf( "%lld %lld %lld", &n, &m, &k );
if( m == k ) subtask1();
else if( m == 2 and k == 1 ) subtask2();
else if( m == 3 and k == 1 ) subtask3();
else if( m == 4 and k == 1 ) subtask4();
else if( m == 4 and k == 2 ) subtask5();
else if( m == 3 and k == 2 ) subtask6();
else subtask7();
return 0;
}