luogu P2000 拯救世界

题目链接

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项系数即为答案,也就是$inom{n + 5 - 1}{5 - 1} = inom{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; 
} 
原文地址:https://www.cnblogs.com/sssy/p/9192081.html