G Give Candies
题意
n n n个糖果, n n n个人从 1 ∼ n 1\sim n 1∼n编号,每次给一个人发糖可以发任意数量但不能小于 1 1 1,直到发完所有糖果,问分糖果的方案有多少种。
分析
1.首先考虑到会不会有一个人被重复发糖,但最后发现对答案没有影响,因为对同一个人发两次糖每次发一颗 和 一次发两颗对于最后的糖果分配结果来看没有区别。
2.考虑会不会有编号的影响,只要对于任意两个方案,只要有编号相同的人持有不同数量的糖果就视为不同方案,也就是说 n = 4 n = 4 n=4,给一个人发 4 4 4个糖果的方案有四种 即给 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4的某一个发 4 4 4个糖果其他人不发。但样例 n = 4 n = 4 n=4时 a n s = 8 ans = 8 ans=8可以分析出来,编号对方案不造成影响,最后的答案按糖果数量排序后,字典序不同才是不同方案 0 , 0 , 0 , 4 = 0 , 4 , 0 , 0 0,0,0,4 = 0,4,0,0 0,0,0,4=0,4,0,0。
3. 此时可以将问题抽象出来:
n
n
n个糖果将其分成
1
,
2
,
…
…
,
n
1,2,……,n
1,2,……,n份的方案数之和,我们采用隔板法。n个糖果共有
n
−
1
n - 1
n−1个地方可以插入隔板,插入
0
0
0个隔板是分成
1
1
1组
C
n
−
1
0
C_{n - 1}^{0}
Cn−10,插入
1
1
1个隔板是分成
2
2
2组
C
n
−
1
1
C_{n - 1}^{1}
Cn−11,……
a
n
s
=
∑
i
=
0
n
−
1
C
n
−
1
i
=
2
n
−
1
ans = \sum_{i = 0}^{n - 1} C_{n - 1}^{i} = 2^{n - 1}
ans=∑i=0n−1Cn−1i=2n−1
4.但是
n
n
n的数据较大
n
<
=
1
0
100000
n <= 10^{100000}
n<=10100000 普通的递推和快速幂都无法满足于是我们需要使用欧拉降幂,将指数的幂降下去,再用快速幂求解。
欧拉降幂结论:
(
a
b
)
m
o
d
p
=
(
a
b
m
o
d
(
p
−
1
)
)
m
o
d
p
(a ^ b) \mod p = (a ^ {b \mod (p - 1)}) \mod p
(ab)modp=(abmod(p−1))modp 当且仅当
a
a
a 与
p
p
p互质。
代码
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int N = 100010;
const int p = 1000000006;//mod - 1
const int mod = 1000000007;//mod
char num[N];
ll ksm(ll a,ll b)
{
ll ans = 1;
while(b)
{
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void solve()
{
scanf("%s",num);
int len = strlen(num);
ll mi = 0;
for(int i = 0; i < len; i ++)
{
mi = mi * 10 % p;
mi = (mi + num[i] - '0') % p;//降幂
}
mi = (mi + p - 1) % p;
printf("%lld\n",ksm(2, mi));
return ;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)solve();
return 0;
}