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 - 高精的更多相关文章

  1. [CEOI2007]树的匹配Treasury(树形DP+高精)

    题意 给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配. N≤1000,其中40%的数据答案不超过 108 题解 显然的树形DP+高精. 这题是作为考试题考 ...

  2. 洛谷P4608 [FJOI2016]所有公共子序列问题 【序列自动机 + dp + 高精】

    题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...

  3. [P1005][NOIP2007] 矩阵取数游戏 (DP+高精)

    我不会高精…… 也不会DP…… 这道题即考高精又考DP…… 我要死了 给一个不是高精的代码(当然不能满分) #include<cstdio> #include<iostream> ...

  4. 矩阵取数问题(dp,高精)

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n×mn \times mn×m的矩阵,矩阵中的每个元素ai,ja_{i,j}ai,j​均为非负整数.游戏规则如下: 每次取数时须从每行各取走 ...

  5. BZOJ1089 [SCOI2003]严格n元树 【dp + 高精】

    Description 如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树.如果该树中最底层的节点深度为d (根的深度为0),那么我们称它为一棵深度为d的严格n元树.例如,深度为2的严 ...

  6. BZOJ5300 [Cqoi2018]九连环 【dp + 高精】

    题目链接 BZOJ5300 题解 这题真的是很丧病,,卡高精卡到哭 我们设\(f[i]\)表示卸掉前\(i\)个环需要的步数 那么 \[f[i] = 2*f[i - 2] + f[i - 1] + 1 ...

  7. bzoj 1089: [SCOI2003]严格n元树【dp+高精】

    设f[i]为深度为i的n元树数目,s为f的前缀和 s[i]=s[i-1]^n+1,就是增加一个根,然后在下面挂n个子树,每个子树都有s[i-1]种 写个高精就行了,好久没写WA了好几次-- #incl ...

  8. 矩阵取数游戏 2007年NOIP全国联赛提高组(dp+高精)

    矩阵取数游戏 2007年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description [问题描述]帅帅经常跟 ...

  9. 【POJ】3378 Crazy Thairs(树状数组+dp+高精)

    题目 传送门:QWQ 分析 题意:给个数列,求有多少五元上升组 考虑简化一下问题:如果题目求二元上升组怎么做. 仿照一下逆序对,用树状数组维护一下就ok了. 三元怎么做呢? 把二元的拓展一位就可以了, ...

随机推荐

  1. BCH分叉是一次站队博弈

    BCH分叉在即,很多人说BCH本次分叉实质是大佬间的斗争,主要是本次BCH分叉主要分为两大派别: 一派以BCH用户量最大的客户端Bitcoin ABC开发组为主,要在11月15日展开硬分叉升级,主要升 ...

  2. Spring IOC 容器源码分析(转)

    原文地址 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢 ...

  3. selector + shape

    selector_shape.xml<?xml version="1.0" encoding="utf-8"?> <selector xmln ...

  4. web 全栈 学习 1 工程师成长思路图

    第一部分: 技术的三个阶段 实现 ---> 借鉴 ---> 优化 实现:为了实现功能,不考虑可读性.借鉴:阅读开源代码,开源程序,学到编程思想.优化:可读性,可执行. 阶段一:实现多做事, ...

  5. iOS中常见的设计模式(MVC/单例/委托/观察者)

    关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...

  6. mini2440 u-boot禁止蜂鸣器

    mini2440的u-boot版本启动之后马上就会开启蜂鸣器,在办公环境下有可能会影响同事的工作,所以我考虑将其禁止掉. 我使用的mini2440使用的光盘是2013年10月的版本,我在该光盘下的u- ...

  7. <密码学入门>关于RSA算法的加密解密及代码实现

    RSA算法 是一种公钥加密算法,RSA算法相比别的算法思路非常清晰,但是想要破解的难度非常大.RSA算法基于一个非常简单的数论事实:两个素数相乘得到一个大数很容易,但是由一个大数分解为两个素数相乘却非 ...

  8. Android窗口系统第一篇---Window的类型与Z-Order确定

    Android的窗口系统是UI架构很重要的一部分,数据结构比较多,细节比较多.本篇文章主要介绍窗口相关数据结构和抽象概念理解,关于[窗口部分的博客]计划如下. 1.窗口Z-Order的管理 2.应用程 ...

  9. html的head中的常见元素

    <head></head>中有charset, title,link 操作系统默认的字符编码就是gbk. html的加强 (1)<a href="#" ...

  10. ubuntn下 apt的用法和yum的比较(转)

    centos有yum安装软件,Ubuntu有apt工具. apt简单的来说,就是给Ubuntu安装软件的一种命令方式. 一.apt的相关文件 /etc/apt/sources.list 设置软件包的获 ...