zoukankan      html  css  js  c++  java
  • Thief in a Shop

    题意:

    问n个物品选出K个可以拼成的体积有哪些。

    解法:

    多项式裸题,注意到本题中 $A(x)^K$ 的系数会非常大,采用NTT优于FFT。

    NTT 采用两个 $2^t+1$ 质数,求原根 $g_n$ 后用 $g_n^1 $~$ g_n^{P-1}$ 的循环代替复数向量的旋转。

    注意逆的 $w_n$ 是 $g_n ^ {  - frac{P-1}{len}  }$,并且要用两个质数保证正确即可,$O(nlogn)$。

    #include <bits/stdc++.h>
    
    #define PI acos(-1)
    #define P1 998244353LL
    #define P2 469762049LL
    #define LL long long
    #define gn 3
    
    const int N = 500010;
    
    using namespace std;
    
    int R[N<<2];
    
    LL qpow(LL x,int n,LL P)
    {
        LL ans = 1;
        for(;n;n>>=1,x = x*x % P) if(n&1) ans = ans*x % P;
        return ans;
    }
    
    void DFT(LL a[],int n,int tp_k,LL P)
    {
        for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]);
        for(int d=1;d<n;d<<=1)
        {
            LL wn = qpow(gn, (P-1)/(d<<1),P);
            if(tp_k == -1) wn = qpow(wn, P-2,P);
            for(int i=0;i<n;i += (d<<1))
            {
                LL wt = 1;
                for(int k=0;k<d;k++, wt = wt*wn % P)
                {
                    LL A0 = a[i+k], A1 = wt * a[i+k+d] % P;
                    a[i+k] = A0+A1;
                    a[i+k+d] = A0+P-A1;
                    if(a[i+k] >= P) a[i+k] -= P;
                    if(a[i+k+d] >= P) a[i+k+d] -= P;
                }
            }
        }
        LL inv = qpow(n, P-2,P);
        if(tp_k==-1)
            for(int i=0;i<n;i++) a[i] = a[i] * inv % P;
    }
    
    LL A[N<<2],B[N<<2];
    
    int main()
    {
        //freopen("test.txt","w",stdout);
        int n,K;
        cin>>n>>K;
        int L = 0,tot;
        while((1<<L)<1000*K) L++;
        tot = (1<<L);
        for(int i=1;i<tot;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        for(int i=1,x;i<=n;i++) scanf("%d",&x), A[x] = 1, B[x] = 1;
        DFT(A,tot,1,P1);
        for(int i=0;i<tot;i++) A[i] = qpow(A[i], K, P1);
        DFT(A,tot,-1,P1);
        DFT(B,tot,1,P2);
        for(int i=0;i<tot;i++) B[i] = qpow(B[i], K, P2);
        DFT(B,tot,-1,P2);
        for(int i=0;i<tot;i++) if(A[i] || B[i]) printf("%d ",i);
        printf("
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    (原创)monitor H3C switch with cacti
    (原创)monitor Dell Powerconnec 6224 with cacti
    (转载)运行主机管理在openvswitch之上
    图片鼠标滑动实现替换
    分布式缓存(一)失效策略和缓存问题击穿,雪崩,穿透
    Spring 事务源码学习
    FactoryBean和BeanFactory
    Spring AOP 源码学习
    “两地三中心”和“双活”
    安装 geopandas 步骤
  • 原文地址:https://www.cnblogs.com/lawyer/p/7190865.html
Copyright © 2011-2022 走看看