luogu P2000 拯救世界
题目链接
题解
按照题目描述构造生成函数
\(1+x^6+x^{12}+\cdots+x^{6k}=\frac{1}{1-x^6}\)
\(1+x+x^2+\cdots+x^9=\frac{1-x^{10}}{1-x}\)
\(1 + x^2 + \cdots + x ^5=\frac{1-x^{6}}{1-x}\)
\(1 + x^4 + x^8 +\cdots + x^{4k} = \frac{1}{1-x^4}\)
\(1 + x ^2 +\cdots + x^7=\frac{1-x^8}{1-x}\)
\(1 + x ^2 + +x^4 +\cdots + x^{2k} = \frac{1}{1-x^2}\)
\(1 + x=\frac{1-x^2}{1-x}\)
\(1 + x ^8 + +x^{16} +\cdots + x^{8k} = \frac{1}{1-x^8}\)
\(1 + x ^{10} + +x^{20} +\cdots + x^{10k} = \frac{1}{1-x^{10}}\)
\(1 + x + x ^ 2 + x ^ 3 = \frac{1 - x^4}{1 - x}\)
把上面的生成函数乘起来,就得到了\(\frac{1}{(1-x)^5}\)
将它展开的生成函数也就是\(1+x+x^2+x^3+\cdots x^n = \frac{1}{1-x}\)的数列自己和自己做五次卷积运算
它的第n项系数即为答案,也就是$\binom{n + 5 - 1}{5 - 1} = \binom{n + 4}{4} $
然后你需要高精度,然后高精度需要fft,人生苦短,woyongpython
那个,不开O2你会T的飞起
代码
// luogu-judger-enable-o2
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
const int maxn = 2000000;
#define pi acos(-1.0)
struct cp {
double x,y;
cp (double a = 0,double b = 0): x(a),y(b) {};
};
cp operator + (cp a,cp b) { return cp(a.x + b.x,a.y + b.y);}
cp operator - (cp a,cp b) { return cp(a.x - b.x,a.y - b.y);}
cp operator * (cp a,cp b) { return cp(a.x * b.x - a.y * b.y,a.x * b.y + a.y * b.x); }
void fft(cp *a,int n, int type) {
for(int i = 0,j = 0;i < n;++ i) {
if(i < j) std::swap(a[i],a[j]);
for(int k = n >> 1;(j ^= k) < k;k >>= 1);
}
for(int m = 2;m <= n;m <<= 1) {
cp w1 = cp(cos(2 * pi / m),type * sin(2 * pi / m));
for(int i = 0;i < n;i += m) {
cp w = cp(1.0,0);
for(int k = 0;k < (m >> 1);++ k) {
cp t = w * a[i + k + (m >> 1)],u = a[i + k];
a[i + k] = u + t;
a[i + k + (m >> 1)] = u - t;
w = w * w1;
}
}
}
}
struct Bignum {
int a[maxn],len;
void clear() {
memset(a,0,sizeof a);len = 0;
}
void read() {
static char s[maxn];
scanf("%s",s);
len = strlen(s);
for(int i = 0;i < len;++ i) a[len - i - 1] = s[i] - '0';
}
void print() {
for(int i = len - 1;i >= 0;i --) putchar(a[i] + '0');
puts("");
}
Bignum operator + (const int &b) const {
Bignum ans;ans.clear();ans.len = len;
for(int i = 0;i <= ans.len;++ i) ans.a[i] = a[i];
ans.a[0] += b;
for(int i = 0;i < ans.len;++ i) {
if(ans.a[i] >= 10) {
ans.a[i] -= 10;ans.a[i + 1] ++;
if(i + 1 == ans.len) ans.len ++;
}
}
return ans;
}
Bignum operator *(const Bignum &b) const {
Bignum ans;ans.clear();
ans.len = len + b.len;
int n; for(n = 1;n < ans.len;n <<= 1);
static cp c[maxn],d[maxn];
for(int i = 0;i < len;i ++) c[i] = cp(a[i],0);
for(int i = len;i < n;++ i) c[i] = cp(0,0);
for(int i = 0;i < b.len;++ i) d[i] = cp(b.a[i],0);
for(int i = b.len;i < n;++ i) d[i] = cp(0,0);
fft(c,n,1);fft(d,n,1);
for(int i = 0;i < n;++ i) c[i] = c[i] * d[i];
fft(c,n,-1);
for(int i = 0;i < n;++ i) c[i].x /= n;
for(int i = 0;i < n;++ i) ans.a[i] = int(c[i].x + 0.5);
for(int i = 0;i < n;++ i) {
ans.a[i + 1] += ans.a[i] / 10;ans.a[i] %= 10;
}
while(ans.a[ans.len - 1] <= 0 && ans.len > 1)ans.len --;
return ans;
}
Bignum operator / (const int & b) const{
Bignum ans;ans.clear();
int e = 0;
for(int i = len - 1;i >= 0;i --) {
e *= 10;e += a[i];
if(e >= b) {
ans.a[ans.len ++] = e / b;e %= b;
} else if(ans.len) { ans.a[ans.len ++] = 0;}
}
if(!ans.len) ans.a[ans.len ++] = 0;
for(int i = 0,j = ans.len - 1;i < j;++ i,-- j)
std::swap(ans.a[i],ans.a[j]);
return ans;
}
}n,n_1,n_2,n_3,n_4;
int main() {
n.read();
n_1 = n + 1;n_2 = n + 2;n_3 = n + 3;n_4 = n + 4;
n_2 = n_2 * n_1;n_3 = n_3 * n_2;n_4 = n_4 * n_3;n_4 = n_4 / 24;
n_4.print();
return 0;
}