sum 题解
题目大意
这道题就是 x 1 + x 2 + x 3 + ⋅ ⋅ ⋅ + x n = N x_1+x_2+x_3+···+x_n=N x1+x2+x3+⋅⋅⋅+xn=N,求有几种组合方法。
思路
利用数学方法中的“隔板法”,不难知道结果就是
C
n
−
1
0
+
C
n
−
1
1
+
C
n
−
1
2
+
⋅
⋅
⋅
+
C
n
−
1
r
+
⋅
⋅
⋅
+
C
n
−
1
n
−
1
C_{n-1}^0+C_{n-1}^1+C_{n-1}^2+···+C_{n-1}^r+···+C_{n-1}^{n-1}
Cn−10+Cn−11+Cn−12+⋅⋅⋅+Cn−1r+⋅⋅⋅+Cn−1n−1.
不难发现这是二项式定理的展开式。
根据二项式定理不难得出,结果就是
2
n
−
1
2^{n-1}
2n−1。
所以,这道题就转换为求解
2
n
−
1
m
o
d
(
1
e
9
+
7
)
2^{n-1}\ mod\ (1e9+7)
2n−1 mod (1e9+7)
可以用费马小定理+快速幂来解题。
首先用费马小定理将指数进行降幂,然后用快速幂取余求得结果。
代码如下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#define pk putchar(' ')
#define ph puts("")
using namespace std;
typedef long long ll;
template <class T>
void rd(T &x)
{
x = 0;
int f = 1;
char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
x *= f;
}
template <class T>
void pt(T x)
{
if (x < 0)
putchar('-'), x = (~x) + 1;
if (x > 9)
pt(x / 10);
putchar(x % 10 ^ 48);
}
template <class T>
T Max(T a, T b)
{
return a > b ? a : b;
}
template <class T>
T Min(T a, T b)
{
return a < b ? a : b;
}
int phi(int x)
{
int res = x;
for (int i = 2;i * i <= x; i++)
if (x % i == 0)
{
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
if (x > 1)
res = res / x * (x - 1);
return res;
}
const int N = 1e5 + 5, mod = 1e9 + 7;
char b[N];
int qkpow(int a, ll b)
{
int res = 1;
while (b)
{
if (b & 1)
res = 1ll * res * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return res;
}
ll low_mi(int mod)
{
int len = strlen(b);
ll ret = 0;
for (int i = 0;i < len; i++)
ret = (ret * 10 + b[i] - 48) % mod;
return ret;
}
int main()
{
while (scanf ("%s", b) != EOF)
{
ll res = low_mi(mod - 1) - 1;
pt(qkpow(2, res)), ph;
}
return 0;
}