朝鲜时蔬(分数据点写算法+毒瘤数学)

本文详细探讨了如何解决给定集合中选取子集,使得子集的元素之和能整除原集合和的问题。针对不同的阶数和价值函数,提出了递归性质和数学归纳的方法,通过枚举和分块策略,逐步计算出最大值出现的子集数量。文章以编程挑战的形式展示了具体实现,涵盖了不同参数组合下的计算策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

朝鲜时蔬

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+(n1),定义其和 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(1mn)阶子集集合 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)={TT={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(1kn)级价值子集集 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)={Tk=sum(T)sum(S)kN+}Sk(S)

就是满足上一个要求的基础上,子集元素和能整除原来的大集合的子集的集合

定义其 m ( 1 ≤ m ≤ n ) m(1\le m\le n) m(1mn) k ( 1 ≤ k ≤ m ) k(1\le k\le m) k(1km)级价值函数为其所有 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)TSm(S)}

定义其 m ( 1 ≤ m ≤ n ) m(1\le m\le n) m(1mn) k ( 1 ≤ k ≤ m ) k(1\le k\le m) k(1km)级价值函数的值点集合 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)={TTk(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} 1n1012

子任务编号分值m=k=
11011
21021
31022
41031
51032
61033
71041
81042
91043
101044

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) x2x1x2(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) x1x2x1(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=ki,k[2,in],即有 ⌊ n i ⌋ − 2 + 1 = ⌊ n i ⌋ − 1 \lfloor\frac{n}{i}\rfloor-2+1=\lfloor\frac{n}{i}\rfloor-1 in2+1=in1

答案为 ∑ i = 1 n ( ⌊ n i ⌋ − 1 ) \sum_{i=1}^n(\lfloor\frac{n}{i}\rfloor-1) i=1n(in1)
按照 ⌊ 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} zx1=x1+x2+x3yx2=x1+x2+x3xx3=x1+x2+x3x1+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<x3x<3x=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+z2(y+z)yz=0(y2)(z2)=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 6x1=x1+x2+x33x2=x1+x2+x32x3=x1+x2+x36x1=3x2=2x3
k = x 1 ⇒ x 2 = 2 k , x 3 = 3 k k=x_1\Rightarrow x_2=2k,x_3=3k k=x1x2=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),kN+,在 n ≥ 3 n\ge 3 n3时存在

要满足 x 1 , x 2 , x 3 ≤ n x_1,x_2,x_3\le n x1,x2,x3n,所以 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=i1,则 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=i1,一定有 i − 1 i-1 i1种拆分方法

但是集合 { 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=1nin2i1[2i]

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<x41>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=wx1x1+x2+x3+x4=zx2x1+x2+x3+x4=yx3x1+x2+x3+x4=xx4
则,有 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 x3,则 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+x4131+41+51+61<1

假设矛盾,所以 1 < x < 3 ⇒ x = 2 1<x<3\Rightarrow x=2 1<x<3x=2

假设 y ≥ 6 y\ge 6 y6,则 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+x4161+71+81<21

假设矛盾,所以 2 < y < 6 ⇒ y = 2 / 3 / 4 2<y<6\Rightarrow y=2/3/4 2<y<6y=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) (z6)(w6)=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) (z4)(w4)=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 (3z10)(3w10)=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 n6的时候才会全都成立,当 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,56n+9n+10n+12n+15n+21nn6

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+x3x1<3(x1+x3)

所以 1 < s < 3 ⇒ s = 2 1<s<3\Rightarrow s=2 1<s<3s=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=5x27x1<5(x1+x2)

所以 2 = s < t < 5 ⇒ t = 3 / 4 2=s<t<5\Rightarrow t=3/4 2=s<t<5t=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 n11时,满足假设条件, 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=1011n+29nn11

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 ni,再计算 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,...i2,则 x 2 = [ 1 , i − 2 ] , . . . , [ 1 , 1 ] x_2=[1,i-2],...,[1,1] x2=[1,i2],...,[1,1]

所以方案数为 ( i − 2 ) + ( i − 1 ) + . . . + 1 = ( i − 1 ) ( i − 2 ) 2 (i-2)+(i-1)+...+1=\frac{(i-1)(i-2)}{2} (i2)+(i1)+...+1=2(i1)(i2)

我们如果能减去这些不合法的形式,再除以六就是拆分的最终方案数了

显然, 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,2i1] 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 32i1,将这个暴力拆开与上面的合并,则会发现 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[3i](别忘了这个形式存在的前提是 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=5i=1nin12i26i+5+3[2i]+4[3i]n6
但是又因为涉及分块,所以计算一段区间内 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值