题意: 给定
n
n
n ,
S
k
S_k
S k 为
x
1
+
x
2
+
.
.
.
+
x
k
=
n
x_1+x_2+...+x_k=n
x 1 + x 2 + . . . + x k = n 的正整数解的方案数,求
(
S
1
+
S
2
+
.
.
.
S
k
)
m
o
d
(
1
0
9
+
7
)
(S_1+S_2+...S_k)\bmod (10^9+7)
( S 1 + S 2 + . . . S k ) m o d ( 1 0 9 + 7 ) 数据范围:
1
<
n
<
1
0
2000
1<n<10^{2000}
1 < n < 1 0 2 0 0 0 注意:当
k
=
2
,
n
=
4
k=2,n=4
k = 2 , n = 4 ,
x
1
=
1
,
x
2
=
3
x_1=1,x_2=3
x 1 = 1 , x 2 = 3 和
x
1
=
3
,
x
2
=
1
x_1=3,x_2=1
x 1 = 3 , x 2 = 1 是两种方案。 题解: 一步步分析,
S
1
S_1
S 1 为
x
1
=
n
x_1=n
x 1 = n 的方案数,自然为
1
1
1 ,
S
2
S_2
S 2 为
x
1
+
x
2
=
n
x_1+x_2=n
x 1 + x 2 = n ,则有
n
−
1
n-1
n − 1 z种方案。可以想到用隔板法来求解每个方案,即
n
n
n 个数构成了
n
−
1
n-1
n − 1 个空,有
k
k
k 个解就要插入
k
−
1
k-1
k − 1 个隔板。那么答案即为
C
n
−
1
0
+
C
n
−
1
1
+
.
.
.
+
C
n
−
1
n
−
2
+
C
n
−
1
n
−
1
=
2
n
−
1
C_{n-1}^0+C_{n-1}^1+...+C_{n-1}^{n-2}+C_{n-1}^{n-1}=2^{n-1}
C n − 1 0 + C n − 1 1 + . . . + C n − 1 n − 2 + C n − 1 n − 1 = 2 n − 1 。 证明即二项式定理:
(
x
+
y
)
n
−
1
=
C
n
−
1
0
x
0
y
n
−
1
+
C
n
−
1
1
x
1
y
n
−
2
+
.
.
.
+
C
n
−
1
n
−
2
x
n
−
2
y
1
+
C
n
−
1
n
−
1
x
n
−
1
y
0
(x+y)^{n-1}=C_{n-1}^0x^0y^{n-1}+C_{n-1}^1x^1y^{n-2}+...+C_{n-1}^{n-2}x^{n-2}y^{1}+C_{n-1}^{n-1}x^{n-1}y^0
( x + y ) n − 1 = C n − 1 0 x 0 y n − 1 + C n − 1 1 x 1 y n − 2 + . . . + C n − 1 n − 2 x n − 2 y 1 + C n − 1 n − 1 x n − 1 y 0 令
x
=
y
=
1
x=y=1
x = y = 1 即可。
本题的
n
n
n 过大,所以无法直接使用快速幂。
根据费马小定理
a
p
−
1
≡
1
(
m
o
d
p
)
,
(
a
,
p
)
=
1
a^{p-1}\equiv1\pmod{p},(a,p)=1
a p − 1 ≡ 1 ( m o d p ) , ( a , p ) = 1 所以
2
n
−
1
=
2
k
×
(
p
−
1
)
+
r
2^{n-1}=2^{k\times{(p-1)}+r}
2 n − 1 = 2 k × ( p − 1 ) + r ,
2
p
−
1
m
o
d
p
=
1
2^{p-1}\bmod p=1
2 p − 1 m o d p = 1 故
2
n
−
1
m
o
d
p
=
2
r
m
o
d
p
2^{n-1}\bmod p=2^{r}\bmod p
2 n − 1 m o d p = 2 r m o d p
欧拉降幂:
2
n
−
1
≡
2
(
n
−
1
)
%
φ
(
p
)
+
φ
(
p
)
2^{n-1}\equiv2^{(n-1)\%φ(p)+φ(p)}
2 n − 1 ≡ 2 ( n − 1 ) % φ ( p ) + φ ( p ) 注意
−
1
-1
− 1 必须最后减去,因为大数边计算边取模,先处理
−
1
-1
− 1 是错误的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7 ;
const int N = 100010 ;
char s[ N] ;
int qp ( int a, int b) {
int ans = 1 ;
while ( b) {
if ( b & 1 ) ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
b >>= 1 ;
}
return ans;
}
int main ( )
{
while ( ~ scanf ( "%s" , s) ) {
int mi = 0 ;
for ( int i = 0 ; s[ i] ; i++ ) mi = ( mi * 10ll + s[ i] - '0' ) % ( mod - 1 ) ;
mi = ( mi - 1 + mod - 1 ) % ( mod - 1 ) ;
int res = qp ( 2 , mi) ;
printf ( "%d\n" , res) ;
}
return 0 ;
}