C - Thief in a Shop - dp完全背包-FFT生成函数

C - Thief in a Shop

 思路 :严格的控制好k的这个数量,这就是个裸完全背包问题.(复杂度最极端会到1e9)

他们随意原来随意组合的方案,与他们都减去 最小的 一个 a[ i ] 组合的方案数目是不会改变的

那么我们就 dp [ i ]表示 i 这个价格需要的最少 个数。  这样求最小个数保证不会漏解

然后 如果这个  i 能通过 1 - k 个物品组合出来,那么 一定能通过k 个物品组合出 i + k * a [ 1 ].

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 1234567
int n,k,dp[maxn],a[maxn];
int v[maxn],mi,sum,id,base;
map<int,bool>vis;
vector<int>ans;
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        if(vis[a[i]]==0)
        {
            vis[a[i]]=1;
            v[++id]=a[i];
        }
    }
    sort(v+1,v+1+id);
    base=v[1]*k;
    for(int i=2; i<=id; i++)
        v[i]-=v[1];
    sum=v[id]*k;
    memset(dp,inf,sizeof(dp));
    dp[0]=0;
    for(int i=2; i<=id; i++)
        for(int j=v[i]; j<=sum; j++)
            dp[j]=min(dp[j],dp[j-v[i]]+1);
    for(int i=0; i<=sum; i++)
    {
        if(dp[i]>k)continue;
            ans.push_back(i+base);
    }
    int len=ans.size();
    for(int i=0; i<len; i++)
    {
        printf("%d",ans[i]);
        if(i<len-1)printf(" ");
        else printf("\n");
    }
    return 0;
}

  思路:最初有的ai 初始化系数为1进行操作k次卷积。注意补零操作,然后注意最大长度,

也就是最终结果可能得到的最大指数 ....

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <cstring>
#include <cmath>
using namespace std;
const double PI = acos(-1.0);
struct complex
{
    double r,i;
    complex(double _r = 0.0,double _i = 0.0)
    {
        r = _r;
        i = _i;
    }
    complex operator +(const complex &b)
    {
        return complex(r+b.r,i+b.i);
    }
    complex operator -(const complex &b)
    {
        return complex(r-b.r,i-b.i);
    }
    complex operator *(const complex &b)
    {
        return complex(r*b.r-i*b.i,r*b.i+i*b.r);
    }
};
void change(complex y[],int len)
{
    int i,j,k;
    for(i = 1, j = len/2; i < len-1; i++)
    {
        if(i < j)swap(y[i],y[j]);
        k = len/2;
        while( j >= k)
        {
            j -= k;
            k /= 2;
        }
        if(j < k) j += k;
    }
}
void fft(complex y[],int len,int on)
{
    change(y,len);
    for(int h = 2; h <= len; h <<= 1)
    {
        complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
        for(int j = 0; j < len; j+=h)
        {
            complex w(1,0);
            for(int k = j; k < j+h/2; k++)
            {
                complex u = y[k];
                complex t = w*y[k+h/2];
                y[k] = u+t;
                y[k+h/2] = u-t;
                w = w*wn;
            }
        }
    }
    if(on == -1)
        for(int i = 0; i < len; i++)
            y[i].r /= len;
}
const int MAXN = 5234567;
complex x1[MAXN],x2[MAXN];
char str1[MAXN/2],str2[MAXN/2];
int sum[MAXN];
int siz[1100];
int main()
{
    int n,k;
    scanf("%d %d", &n, &k);
    int x;
    int MAX = 0;
    memset(siz,0,sizeof(siz));
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &x);
        siz[x] = 1;
        MAX = max(MAX,x);
    }
    int len1 = MAX * k;
    int len = 1;
    while(len < len1) len <<= 1;
    for(int i = 0; i < len; i++)
        x1[i] = complex(siz[i],0);
    x2[0] = complex(1,0);
    for(int i=1; i < len; i++)
        x2[i] = complex(0,0);
    fft(x1,len,1);
    fft(x2,len,1);
    while(k)
    {
        if(k % 2 == 1)
        {
            for(int i = 0; i <len; i++)
                x2[i] = x1[i]*x2[i];
            fft(x2,len,-1);
            for(int i = 0; i < len; i++)
            {
                sum[i] = (int)(x2[i].r + 0.5);
                if(sum[i])x2[i]=complex(1,0);
                else x2[i]=complex(0,0);
            }
            fft(x2,len,1);
        }
        for(int i =0; i < len; i++)
            x1[i] = x1[i]*x1[i];
        fft(x1,len,-1);
        for(int i = 0; i < len; i++)
        {
            sum[i] = (int)(x1[i].r + 0.5);
            if(sum[i])x1[i]=complex(1,0);
            else x1[i]=complex(0,0);
        }
        fft(x1,len,1);
        k /= 2;
    }
    fft(x2,len,-1);
    for(int i = 0; i < len; i++)
    {
        sum[i] = (int)(x2[i].r + 0.5);
    }
    for(int i = 0; i <len; i++)
    {
        if(sum[i])
            printf("%d ",i);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值