zoukankan      html  css  js  c++  java
  • 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; 
    } 
    
  • 相关阅读:
    倍数求和
    最大(小)值
    数组扁平化:(多维数组 -> 一维数组)
    任意数求和
    找到重复最多项
    Linux 标准 I/O 库
    Linux文件操作函数
    Linux文件的IO操作 一
    Linux文件系统概述二
    Linux文件系统概述
  • 原文地址:https://www.cnblogs.com/sssy/p/9192081.html
Copyright © 2011-2022 走看看