zoukankan      html  css  js  c++  java
  • 鬼魅 分拆数

    https://loj.ac/problem/6268  模板题。  

    一: 生成函数? 多项式exp?(最慢?) https://www.cnblogs.com/Kong-Ruo/p/10716004.html  (原文)

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0, f = 1;
        char ch;
        for (ch = getchar(); !isdigit(ch); ch = getchar())
            if (ch == '-')
                f = -f;
        for (; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 600010, mod = 998244353;
    int F[maxn], G[maxn];
    inline int skr(int x, int t) {
        int res = 1;
        for (; t; x = 1LL * x * x % mod, t >>= 1)
            if (t & 1)
                res = 1LL * res * x % mod;
        return res;
    }
    int r[maxn], lg[maxn], temp[maxn];
    int inv[maxn], ifac[maxn], fac[maxn];
    inline int skr(int x, LL t) {
        int res = 1;
        while (t) {
            if (t & 1)
                res = 1LL * res * x % mod;
            x = 1LL * x * x % mod;
            t = t >> 1;
        }
        return res;
    }
    inline void fft(int *a, int n, int type) {
        for (int i = 0; i < n; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lg[n] - 1));
        for (int i = 0; i < n; i++)
            if (i < r[i])
                swap(a[i], a[r[i]]);
        for (int i = 1; i < n; i <<= 1) {
            int wn = skr(3, (mod - 1) / (i << 1));
            if (type == -1)
                wn = skr(wn, mod - 2);
            // cout << wn << endl;
            for (int j = 0; j < n; j += (i << 1)) {
                int w = 1;
                for (int k = 0; k < i; k++, w = (1LL * (LL)w * (LL)wn) % mod) {
                    int x = a[j + k], y = (1LL * (LL)w * (LL)a[j + k + i]) % mod;
                    a[j + k] = (x + y) % mod;
                    a[j + k + i] = (((x - y) % mod) + mod) % mod;
                }
            }
        }
        if (type == -1) {
            int inv = skr(n, mod - 2);
            for (int i = 0; i < n; i++) a[i] = ((LL)a[i] * (LL)inv) % mod;
        }
    }
    inline void Inverse(int *a, int *b, int n) {
        if (n == 1) {
            b[0] = skr(a[0], mod - 2);
            return;
        }
        Inverse(a, b, n >> 1);
        memcpy(temp, a, n * sizeof(int));
        memset(temp + n, 0, n * sizeof(int));
        fft(temp, n << 1, 1);
        fft(b, n << 1, 1);
        for (int i = 0; i < (n << 1); i++)
            b[i] = 1LL * b[i] * ((2LL - 1LL * temp[i] * b[i] % mod + mod) % mod) % mod;
        fft(b, n << 1, -1);
        memset(b + n, 0, n * sizeof(int));
    }
    int c[maxn], d[maxn];
    inline void Ln(int *a, int *b, int n) {
        Inverse(a, c, n);
        for (int i = 0; i < n - 1; ++i) d[i] = (LL)(i + 1) * a[i + 1] % mod;
        d[n - 1] = 0;
        fft(c, n << 1, 1);
        fft(d, n << 1, 1);
        for (int i = 0; i < (n << 1); ++i) c[i] = 1LL * d[i] * c[i] % mod;
        fft(c, (n << 1), -1);
        for (int i = 1; i < (n << 1); ++i) b[i] = 1LL * inv[i] * c[i - 1] % mod;
        b[0] = 0;
        for (int i = 0; i < (n << 1); ++i) c[i] = d[i] = 0;
    }
    int temp_w[maxn], temp_Ln[maxn];
    inline void Exp(int *a, int *b, int n) {
        if (n == 1) {
            b[0] = 1;
            return;
        }
        Exp(a, b, n >> 1);
        memcpy(temp_w, b, sizeof(int) * n);
        memset(temp_w + n, 0, sizeof(int) * n);
        Ln(b, temp_Ln, n);
        for (int i = 0; i < n; i++) temp_Ln[i] = (mod + a[i] - temp_Ln[i]) % mod;
        (temp_Ln[0] += 1) %= mod;
        fft(temp_w, n << 1, 1);
        fft(temp_Ln, n << 1, 1);
        for (int i = 0; i < (n << 1); i++) temp_w[i] = 1LL * temp_w[i] * temp_Ln[i] % mod;
        fft(temp_w, n << 1, -1);
        memcpy(b, temp_w, n * sizeof(int));
        memset(b + n, 0, n * sizeof(int));
        memset(temp_w, 0, sizeof(int) * (n << 1));
        memset(temp_Ln, 0, sizeof(int) * (n << 1));
    }
    int main() {
        int n = read(); lg[0] = -1;
        rep(i, 1, 600000) lg[i] = lg[i >> 1] + 1;
        int len = 1; for(; len <= n; len <<= 1);
        inv[1] = ifac[0] = fac[0] = 1;
        rep(i, 1, len) {
            if (i != 1) inv[i] = -(LL)mod / i * inv[mod % i] % mod;
            inv[i] = ((inv[i] % mod) + mod) % mod;
            ifac[i] = (LL)ifac[i - 1] * inv[i] % mod;
            fac[i] = (LL)fac[i - 1] * i % mod;
        }
        rep(i, 1, n) rep(j, 1, n / i) F[i * j] = (F[i * j] + inv[j]) % mod;
        //rep(i, 1, n) cout << F[i] << " ";
        //cout << endl;
        Exp(F, G, len); rep(i, 1, n) cout << G[i] << '
    ';
    }
    View Code

    二: dp?? 背包?  (较慢?)  原文:https://www.cnblogs.com/JYYHH/p/8954965.html

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100005,root=3,ha=998244353,inv=ha/3+1,Base=333;
    inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
    void W(int x){ if(x>=10) W(x/10); putchar(x%10+'0');}
    int A[maxn*4],F[Base+5][maxn],B[maxn*4],r[maxn*4],n,l,S,N,INV;
    inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha; return an;}
     
    inline void dp(){
        A[0]=1;
        for(int i=1;i<Base;i++)
            for(int j=i;j<=n;j++) ADD(A[j],A[j-i]);
             
        F[0][0]=1,S=maxn/Base+1,F[1][Base]=1;
        for(int i=1;i<S;i++)
            for(int j=0;j<=n;j++) if(F[i][j]){
                if(j+i<=n) ADD(F[i][j+i],F[i][j]);
                if(j+Base<=n) ADD(F[i+1][j+Base],F[i][j]);
                ADD(B[j],F[i][j]);
            }
        ADD(B[0],1);
    }
     
    inline void NTT(int *c,int f){
        for(int i=0;i<N;i++) if(i<r[i]) swap(c[i],c[r[i]]);
         
        for(int i=1;i<N;i<<=1){
            int omega=ksm((f==1?root:inv),(ha-1)/(i<<1));
            for(int P=i<<1,j=0;j<N;j+=P){
                int now=1;
                for(int k=0;k<i;k++,now=now*(ll)omega%ha){
                    int x=c[j+k],y=c[j+k+i]*(ll)now%ha;
                    c[j+k]=add(x,y);
                    c[j+k+i]=add(x,ha-y);
                }
            }
        }
         
        if(f==-1) for(int i=0;i<N;i++) c[i]=c[i]*(ll)INV%ha;
    }
     
    int main(){
        scanf("%d",&n),dp();
         
        for(N=1;N<=(n<<1);N<<=1) l++;
        for(int i=0;i<N;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
        NTT(A,1),NTT(B,1);
        for(int i=0;i<N;i++) A[i]=A[i]*(ll)B[i]%ha;
        INV=ksm(N,ha-2),NTT(A,-1);
         
        for(int i=1;i<=n;i++) W(A[i]),puts("");
        return 0;
    }
    View Code

    三:数论与五边形数定理? (最快?) 原文:https://blog.csdn.net/weixin_41698125/article/details/79334581

    步骤:

        一、构造母函数(像上面那样)并化简成1/[(1-x)*(1-x^2)*(1-x^3)*...](化简可参见无穷级数)

        二、分析(1-x)*(1-x^2)*(1-x^3)*...(这个函数也叫欧拉函数)的系数。(结论:系数的通项为 k*(3k±1)/2)(这个东西证明起来十分复杂,自行百度五边形数定理)

        三、p(n)与欧拉函数的关系,通过分析n次项系数可得p(n)-p(n-1)-p(n-2)+p(n-5)+p(n-7)-p(n-12)-p(n-15)+…-…=0

        于是我们可以用前几项的p(n)来得到新的p(n),这是效率相当高的方法。时间复杂度o(n^3/2)。

    #include <iostream>
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    #include <cmath>
    #include <deque>
    #include <vector>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <map>
    #include <stack>
    #include <set>
    #define LL long long
    #define ULL unsigned long long
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define dep(i,j,k) for(int i=k;i>=j;i--)
    #define INF 0x3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    #define make(i,j) make_pair(i,j)
    #define pb push_back
    using namespace std;
    const int N = 1e5 + 5;
    const LL mod = 998244353;
    LL p[N];
    LL get(LL n) {
        LL res = 0, k = 1, a = 2, b = 1, s = 1;
        while (n >= a){
            res += s * (p[n - a] % mod + p[n - b] % mod) % mod;
            res = ( res + mod) % mod;
            a += 3 * k + 2;
            b += 3 * k + 1;
            s *= -1;
            k += 1;
        }
        res += (n >= b) ? s * p[n - b] : 0;
        return ( res + mod ) % mod;
    }
    int main() {
        p[0] = p[1] = 1LL;
        rep(i, 2, N - 5) {
            p[i] = get(1LL * i) % mod;
        }
        int n;
        scanf("%d", &n);
        rep(i, 1, n) {
            printf("%lld
    ", p[i]);
            //if(p[i] < 0 ) break;
        }
        return 0;
    }
    View Code
    一步一步,永不停息
  • 相关阅读:
    【2021-05-18】人生十三信条
    【2021-05-17】打了第一针疫苗
    【2021-05-16】该工作时好好工作,该休息时好好休息
    【2021-05-15】人生十三信条
    【2021-05-14】要保持团队作战的模式
    【2021-05-13】罗马不是一天能建成的
    【2021-05-12】己所不欲勿施于人
    【2021-05-11】服务好了别人,也就服务好了自己
    二维区域和检索
    寻找重复数
  • 原文地址:https://www.cnblogs.com/Willems/p/11041765.html
Copyright © 2011-2022 走看看