SCUT - 299 - Kaildls的数组划分 - dp - 高精
https://scut.online/p/299
\(dp[i][k]\) 为前 \(i\) 个数分 \(k\) 组的最大值,那么 $dp[i][k]=max_{p=1}^{i-1}{dp[p][k-1]*sum(p+1,i)} $
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct BigInt {
    const static int mod = 10000;
    const static int DLEN = 4;
    vector<int> a;
    int len;
    BigInt() {
        a.resize(1);
        len = 1;
    }
    BigInt(int v) {
        a.resize(2);
        len = 0;
        do {
            a[len++] = v%mod;
            v /= mod;
        } while(v);
    }
    BigInt operator +(const BigInt &b)const {
        BigInt res;
        res.len = max(len,b.len);
        res.a.resize(res.len+1);
        for(int i = 0; i <= res.len; i++)
            res.a[i] = 0;
        for(int i = 0; i < res.len; i++) {
            res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0);
            res.a[i+1] += res.a[i]/mod;
            res.a[i] %= mod;
        }
        if(res.a[res.len] > 0)
            res.len++;
        return res;
    }
    BigInt operator *(const BigInt &b)const {
        BigInt res;
        res.a.resize(len + b.len);
        for(int i = 0; i < len; i++) {
            int up = 0;
            for(int j = 0; j < b.len; j++) {
                int temp = a[i]*b.a[j] + res.a[i+j] + up;
                res.a[i+j] = temp%mod;
                up = temp/mod;
            }
            if(up != 0)
                res.a[i + b.len] = up;
        }
        res.len = len + b.len;
        while(res.a[res.len - 1] == 0 &&res.len > 1)
            res.len--;
        res.a.resize(res.len);
        return res;
    }
    bool operator >(const BigInt &b)const {
        if(len>b.len)
            return true;
        else if(len==b.len) {
            int ln=len-1;
            while(a[ln]==b.a[ln]&&ln>=0)
                ln--;
            if(ln>=0&&a[ln]>b.a[ln])
                return true;
            else
                return false;
        } else
            return false;
    }
    void output() {
        printf("%d",a[len-1]);
        for(int i = len-2; i >=0 ; i--)
            printf("%04d",a[i]);
        printf("\n");
    }
};
int a[205];
BigInt dp[205][205];
//区间[i,j]分为k段取得的最大值
inline int suma(int i,int j) {
    return a[j]-a[i-1];
}
int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++) {
        scanf("%d",&a[i]);
    }
    for(int i=1; i<=n; i++) {
        a[i]+=a[i-1];
    }
    for(int i=1; i<=n; i++)
        dp[i][1]=BigInt(suma(1,i));
    for(int i=2; i<=n; i++) {
        int c=min(i,k);
        for(int ki=2; ki<=c; ki++) {
            for(int p=1; p<=i-1; p++) {
                BigInt t=dp[p][ki-1]*BigInt(suma(p+1,i));
                if(t>dp[i][ki])
                    dp[i][ki]=t;
            }
        }
    }
    dp[n][k].output();
}
带FFT优化,反而更慢。这个可以理解。本身乘法是\(O(nm)\),这里m小到不行。你还搞个\(O(nlogn)\)?
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6+10;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')
            f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const double Pi=acos(-1.0);
struct Complex {
    double x,y;
    Complex(double xx=0,double yy=0) {
        x=xx,y=yy;
    }
    Complex operator+(const Complex& b)const {
        return Complex(x+b.x,y+b.y);
    }
    Complex operator-(const Complex& b)const {
        return Complex(x-b.x,y-b.y);
    }
    Complex operator*(const Complex& b)const {
        return Complex(x*b.x-y*b.y,x*b.y+y*b.x);
    }
} a[MAXN],b[MAXN];
int l,r[MAXN];
int limit;
void FFT(Complex *A,int type) {
    for(int i=0; i<limit; i++)
        if(i<r[i])
            swap(A[i],A[r[i]]);
    for(int mid=1; mid<limit; mid<<=1) {
        Complex Wn(cos(Pi/mid), type*sin(Pi/mid));
        for(int R=mid<<1,j=0; j<limit; j+=R) {
            Complex w(1,0);
            for(int k=0; k<mid; k++,w=w*Wn) {
                Complex x=A[j+k],y=w*A[j+mid+k];
                A[j+k]=x+y;
                A[j+mid+k]=x-y;
            }
        }
    }
}
void Mult(const int &n,const int &m,const vector<int> &A,const vector<int> &B) {
    for(limit=1,l=0; limit<=n+m;limit<<=1)
        l++;
    memset(a,0,sizeof(a[0])*limit);
    memset(b,0,sizeof(b[0])*limit);
    for(int i=0; i<=n; i++)
        a[i].x=A[i];
    for(int i=0; i<=m; i++)
        b[i].x=B[i];
    for(int i=0; i<limit; i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    FFT(a,1);
    FFT(b,1);
    for(int i=0; i<=limit; i++)
        a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=0; i<=n+m+2; i++) {
        a[i].x=(ll)(a[i].x/limit+0.5);
    }
    return;
}
struct BigInt {
    const static int mod = 10000;
    const static int DLEN = 4;
    vector<int> a;
    int len;
    BigInt() {
        a.resize(4);
        len = 1;
    }
    BigInt(int v) {
        a.resize(4);
        len=0;
        do {
            a[len++]=v%mod;
            v/=mod;
        } while(v);
    }
    BigInt operator +(const BigInt &b)const {
        BigInt res;
        res.len=max(len,b.len);
        res.a.resize(res.len+4);
        for(int i=0; i<res.len; i++) {
            res.a[i]+=((i<len)?a[i]:0)+((i<b.len)?b.a[i]:0);
            res.a[i+1]+=res.a[i]/mod;
            res.a[i]%=mod;
        }
        if(res.a[res.len]>0)
            res.len++;
        return res;
    }
    BigInt operator *(const BigInt &b)const {
        BigInt res;
        res.a.resize(len+b.len+4);
        for(int i=0; i<len; i++) {
            int up=0;
            for(int j=0; j<b.len; j++) {
                int temp=a[i]*b.a[j]+res.a[i+j]+up;
                res.a[i+j]=temp%mod;
                up=temp/mod;
            }
            if(up != 0)
                res.a[i+b.len]=up;
        }
        res.len=len+b.len;
        while(res.len>1&&res.a[res.len-1]==0)
            res.len--;
        return res;
    }
    bool operator >(const BigInt &b)const {
        if(len>b.len)
            return true;
        else if(len==b.len) {
            int ln=len-1;
            while(a[ln]==b.a[ln]&&ln>=0)
                ln--;
            if(ln>=0&&a[ln]>b.a[ln])
                return true;
            else
                return false;
        } else
            return false;
    }
    void output() {
        printf("%d",a[len-1]);
        for(int i=len-2; i>=0; i--)
            printf("%04d",a[i]);
        printf("\n");
    }
};
BigInt BigInt_Mult_FFT(const BigInt &A,const BigInt &B) {
    Mult(A.len-1,B.len-1,A.a,B.a);
    BigInt res;
    res.len=A.len+B.len-1;
    res.a.resize(res.len+4);
    for(int i=0; i<res.len; i++)
        res.a[i]=a[i].x;
    while(res.len>1&&res.a[res.len-1]==0)
        res.len--;
    for(int i=0; i<res.len; i++) {
        res.a[i+1]+=res.a[i]/BigInt::mod;
        res.a[i]%=BigInt::mod;
    }
    if(res.a[res.len]>0)
        res.len++;
    return res;
}
int arr[205];
BigInt dp[205][205];
//区间[i,j]分为k段取得的最大值
inline int sumarr(int i,int j) {
    return arr[j]-arr[i-1];
}
int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1; i<=n; i++) {
        scanf("%d",&arr[i]);
    }
    for(int i=1; i<=n; i++) {
        arr[i]+=arr[i-1];
    }
    for(int i=1; i<=n; i++) {
        dp[i][1]=BigInt(sumarr(1,i));
    }
    for(int i=2; i<=n; i++) {
        int c=min(i,k);
        for(int ki=2; ki<=c; ki++) {
            for(int p=1; p<=i-1; p++) {
                //BigInt t=dp[p][ki-1]*BigInt(sumarr(p+1,i));
                BigInt t=BigInt_Mult_FFT(dp[p][ki-1],BigInt(sumarr(p+1,i)));
                if(t>dp[i][ki]) {
                    dp[i][ki]=t;
                }
            }
        }
    }
    dp[n][k].output();
}
												
											SCUT - 299 - Kaildls的数组划分 - dp - 高精的更多相关文章
- [CEOI2007]树的匹配Treasury(树形DP+高精)
		
题意 给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配. N≤1000,其中40%的数据答案不超过 108 题解 显然的树形DP+高精. 这题是作为考试题考 ...
 - 洛谷P4608 [FJOI2016]所有公共子序列问题  【序列自动机 + dp + 高精】
		
题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...
 - [P1005][NOIP2007] 矩阵取数游戏 (DP+高精)
		
我不会高精…… 也不会DP…… 这道题即考高精又考DP…… 我要死了 给一个不是高精的代码(当然不能满分) #include<cstdio> #include<iostream> ...
 - 矩阵取数问题(dp,高精)
		
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n×mn \times mn×m的矩阵,矩阵中的每个元素ai,ja_{i,j}ai,j均为非负整数.游戏规则如下: 每次取数时须从每行各取走 ...
 - BZOJ1089 [SCOI2003]严格n元树   【dp + 高精】
		
Description 如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树.如果该树中最底层的节点深度为d (根的深度为0),那么我们称它为一棵深度为d的严格n元树.例如,深度为2的严 ...
 - BZOJ5300 [Cqoi2018]九连环  【dp + 高精】
		
题目链接 BZOJ5300 题解 这题真的是很丧病,,卡高精卡到哭 我们设\(f[i]\)表示卸掉前\(i\)个环需要的步数 那么 \[f[i] = 2*f[i - 2] + f[i - 1] + 1 ...
 - bzoj 1089: [SCOI2003]严格n元树【dp+高精】
		
设f[i]为深度为i的n元树数目,s为f的前缀和 s[i]=s[i-1]^n+1,就是增加一个根,然后在下面挂n个子树,每个子树都有s[i-1]种 写个高精就行了,好久没写WA了好几次-- #incl ...
 - 矩阵取数游戏  2007年NOIP全国联赛提高组(dp+高精)
		
矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description [问题描述]帅帅经常跟 ...
 - 【POJ】3378 Crazy Thairs(树状数组+dp+高精)
		
题目 传送门:QWQ 分析 题意:给个数列,求有多少五元上升组 考虑简化一下问题:如果题目求二元上升组怎么做. 仿照一下逆序对,用树状数组维护一下就ok了. 三元怎么做呢? 把二元的拓展一位就可以了, ...
 
随机推荐
- mybatis 运算符转义收录
			
在ibatis配置文件写SQL语句的时候对于一些比如“<”,">","<>","&"," ' &q ...
 - ExtJS教程(5)---Ext.data.Model之高级应用
			
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jaune161/article/details/37391399 1.Model的数据验证 这里借助 ...
 - LeetCode:用最少的箭引爆气球【452】
			
LeetCode:用最少的箭引爆气球[452] 题目描述 在二维空间中有许多球形的气球.对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标.由于它是水平的,所以y坐标并不重要,因此只要知道 ...
 - jQuery/CSS3实现Android Dock效果
			
在线演示 本地下载
 - BeginPaint和GetDC有什么区别
			
windows编程问题 第一种情况显示出来的字很正常. case WM_PAINT: gdc = BeginPaint (hwnd, &ps); TextOut (gdc, 0, 0, s, ...
 - zabbix 监控 haproxy 记录
			
1. 当配置好后,遇到 Value should be a JSON object. 该如何是好? sudo 文件增加: zabbix ALL=(ALL) NOPASSWD: ALL haproxy ...
 - Eclipse中导入github上的项目
			
Eclipse中导入github上的项目 转载至: http://blog.csdn.net/hil2000/article/details/8566456 1.首先在github.com上申请一个账 ...
 - html5--1.18 div元素与布局
			
1.18 div元素与布局 1.元素的分类2.div元素与布局 1.元素的分类 块元素:主要特征是会产生换行效果,自动与其他元素分离成两行:通常可以作为容器在内部添加其他元素. 已经学过的块元素有: ...
 - kvm初体验之五:vm连接网络的两种方式:bridge和nat
			
1. 在安装vm时指定网络连接方式 1)bridge virt-install --name vm1 --ram=1024 --vcpus=1 --disk path=/vm-images/vm1,s ...
 - tensorflow 线性回归 iris
			
线性拟合