[DP之普通系列]
noip快要来了 要练练dp 难度也挺接近 还是挺好的
[Usaco2013 Nov]Pogo-Cow |
这一道题要下一段大于这一段 所以的话我们就要记录每一段的状态 F[i,j]=F[j,k]+A[i] (j-i<=k-j, i<j<k)
然后我们可以优化一下 k是可以二分处理的 F[i,j]=F[j,k-n]+A[i] 然后就是树状数组优化一下 写到一半才发现可以写优先队列..
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define Maxn 1010
using namespace std;
bool Cmp(const pair<int,int> &x,const pair<int,int> &y){return x.first<y.first;}
pair<int,int>pr[Maxn]; int tr[Maxn][Maxn];
int low_bit(int x){return x&(-x);} int N;
void Add(int k,int x,int c){while(x<=N) {tr[k][x]=max(tr[k][x],c); x+=low_bit(x);}}
int Find(int k,int x){int maxx=; while(x>=){maxx=max(maxx,tr[k][x]); x-=low_bit(x);} return maxx;}
int twopart1(int x,int c)
{
int ret=-; int L=x; int R=N;
while(L<=R)
{
int mid=(L+R)>>;
if(pr[mid].first-pr[x].first>=c) R=mid-,ret=mid;
else L=mid+;
}
return ret;
} int twopart2(int x,int c)
{
int ret=-; int L=; int R=x;
while(L<=R)
{
int mid=(L+R)>>;
if(pr[x].first-pr[mid].first>=c) L=mid+,ret=mid;
else R=mid-;
}
return ret;
}
int main()
{
scanf("%d",&N);
for(int i=;i<=N;i++) scanf("%d%d",&pr[i].first,&pr[i].second);
sort(pr+,pr+N+,Cmp); memset(tr,,sizeof(tr)); int Maxx=;
for(int i=;i<=N;i++) for(int j=i+;j<=N;j++) Add(i,N-j+,pr[i].second+pr[j].second),Maxx=max(Maxx,Find(i,N-j+));
for(int i=N;i>=;i--)
{
for(int j=i+;j<=N;j++)
{
int k=twopart1(j,pr[j].first-pr[i].first);
if(k!=-) Add(i,N-j+,Find(j,N-k+)+pr[i].second);
Maxx=max(Maxx,Find(i,N-j+));
}
} memset(tr,,sizeof(tr));
for(int i=;i<=N;i++) for(int j=;j<i;j++) Add(i,j,pr[i].second+pr[j].second),Maxx=max(Maxx,Find(i,j));
for(int i=;i<=N;i++)
{
for(int j=;j<i;j++)
{
int k=twopart2(j,pr[i].first-pr[j].first);
if(k!=-) Add(i,j,Find(j,k)+pr[i].second);
Maxx=max(Maxx,Find(i,j));
}
}
return printf("%d\n",Maxx),;
}
/*
6
5 6
1 1
10 5
7 6
4 8
8 10
*/
hdu5291 Candy Distribution
多校的题哦很激动 很少碰到
然后yy了一下 一下子想到了 F[i][j]表示选i份 A与B差为j 方案数大小
然后转移是 F[i][j]=F[i-1][k]*floor((A[i]-|j-k|)/2)+1
然后好像是N^4的 好像不行 怎么办好呢
看题解咯
其实每一层都对下一层有关系 我们不妨写成F[i][j+k或j-k]+=F[i-1][j]*floor((A[i]-k)/2)+1
那么的话我们会发现这个有个下去整 也就是和奇数和偶数有关 然后每次都是递增或者递减的 就是乘于F[i-1][j]的次数是递增或者是递减1的
然后怎么搞呢 我们对于每一个F[i]搞一下 去更新F[i+1] 然后拿一个指针跳下标每次加2 用一个差不多lazy的数组打每个位置的值
我们想想 每一次F[i][j]转移的时候 只要在开头前面打一个F[i][j] 然后途中递增的时候每一次都加上之前的lazy lazy就相当于每一次增加的量
然后递减的时候标记减两次F[i][j] 这样的话lazy变成-F[i][j]所以每次都会减掉F[i][j] 然后最后的时候再加一个 使全部都不增不减 免得影响后面
我们途中可以优化一下 就是每一次最多能到达的点就是加减前面所有A[i]的总和 这样速度快一倍
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define Maxn 210
using namespace std;
const int Mod=1e9+;
const int Maxm=; int F[][]; int B[];
int T,N; int A[Maxn]; int cur;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&N); for(int i=;i<=N;i++) scanf("%d",&A[i]); int cur=;
memset(F,,sizeof(F)); F[cur][]=; int tot=;
for(int i=;i<N;i++)
{
tot+=A[i+];
for(int j=-tot-;j<=+tot+;j++) B[j]=,F[cur^][j]=;
for(int j=-tot;j<=+tot;j++)
{
if(F[cur][j])
{
B[j-A[i+]-]=(B[j-A[i+]-]+F[cur][j])%Mod;
B[j-A[i+]-]=(B[j-A[i+]-]+F[cur][j])%Mod; B[j-]=(B[j-]-F[cur][j])%Mod;
B[j+]=(B[j+]-F[cur][j])%Mod;
B[j]=(((B[j]-F[cur][j])%Mod)-F[cur][j])%Mod; B[j+A[i+]+]=(B[j+A[i+]+]+F[cur][j])%Mod;
B[j+A[i+]+]=(B[j+A[i+]+]+F[cur][j])%Mod; }
}
int last=,ans=;
for(int j=-tot-;j<=+tot+;j+=)
{
ans=(ans+last)%Mod;
F[cur^][j]=(ans+Mod)%Mod;
last=(last+B[j])%Mod;
}
last=; ans=;
for(int j=-tot-;j<=+tot+;j+=)
{
ans=(ans+last)%Mod;
F[cur^][j]=(ans+Mod)%Mod;
last=(last+B[j])%Mod;
}cur^=;
}
printf("%d\n",F[cur][]);
}
return ;
}
/*
2
1
2
2
1 2
*/
CH Round #54 - Streaming #5 (NOIP模拟赛Day1) 高维网络
这一道题非常noip提高组第三题 出得非常好 我看了看范围可以尽能力水70应该是没什么问题的
这题因为P小 所以从P下手 然后就是上图了
我想补充的是P=0的做法 就是一个组合数学 你想想在D维空间下 你从A走到B 是要走sigma(Ai)步的 那么我把每一维都变成一个序列1 2 3 ... A[i]
那么就是变成了我在sigma(Ai)步中 让这些序列组合起来 然后每一个序列的数 一定在一些位置上抽出来后也是从小到大的
那么就等于这样的组合数 很抽象吧 等于从空间上走一维 就在一个格子上填一个数
怎么算呢 我们以三个序列个数为例 x,y,z
=C(x,x+y+z)*C(y,y+z) 什么意思呢 就是我现在x+y+z个格子上填x个 就把x给搞完了 然后在其他剩余填y-z的格子上再填y 然后相乘(这不用解释吧 x能填的方案和其他格子的方案相乘)
然后化简得p=0的式子
这道题还有一个妙的地方就是把所有不合法的路径等于以某个点为起始点 第一个不合法的点 到终点的不合法路径的总和 这样的话保证不会重复(我觉得非常妙可能是我太弱了)
exgcd求逆元好像会快很多
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define Maxn 510
using namespace std;
typedef long long LL;
const LL Mod=1e9+;
struct node{LL A[Maxn];}Q[Maxn]; LL D,P;
bool Cmp(const node &x,const node &y)
{
for(LL i=;i<=D;i++) if(x.A[i]!=y.A[i]) return x.A[i]<y.A[i];
return ;
}
LL DP[Maxn]; bool check(LL x,LL y){for(LL i=;i<=D;i++) if(Q[x].A[i]>Q[y].A[i]) return ; return ;}
LL ny[]; LL pre[];
void exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==){x=; y=; return ;}
else{LL tx,ty; exgcd(b,a%b,tx,ty); x=ty; y=tx-(a/b)*ty;}
} LL Sum[]; LL part(LL x,LL y)
{
LL s=; LL p=;
for(LL i=;i<=D;i++)
{
s+=Q[y].A[i]-Q[x].A[i];
p=(p*(pre[Q[y].A[i]-Q[x].A[i]]))%Mod;
}
return ((Sum[s]*p)%Mod+Mod)%Mod;
} int main()
{
for(LL i=;i<=;i++){LL x,y; exgcd(i,Mod,x,y); ny[i]=x;}
pre[]=; for(LL i=;i<=;i++){pre[i]=(pre[i-]*ny[i])%Mod;}
Sum[]=; for(LL i=;i<=;i++) Sum[i]=(Sum[i-]*i)%Mod;
scanf("%lld%lld",&D,&P);
for(LL j=;j<=D;j++) scanf("%lld",&Q[P+].A[j]);
for(LL i=;i<=P;i++) for(LL j=;j<=D;j++) scanf("%lld",&Q[i].A[j]);
for(LL j=;j<=D;j++) Q[].A[j]=;
P++; sort(Q,Q+P+,Cmp); for(LL i=;i<=P;i++)
{
DP[i]=part(,i);
for(LL j=;j<i;j++)
if(check(j,i)) DP[i]=(DP[i]-(DP[j]*part(j,i))%Mod+Mod)%Mod;
}
return printf("%lld\n",DP[P]),;
}
/*
2 1
2 1
1 0
A[i]<=100000 D<=100 P<=500
*/
这一道题应该放在提高组的第二题左右吧
一开始想暴力dp水分 发现错了 F[i][j]大概表示选了i个人剩下j的花费的方案 发现转移很慢 而且还会有错
然后换思路 我们发现如果Ai>Aj i>j 的话 这个Ai是没意义的
那么我们不妨从小到大排 然后把每个数插在最前面或者最后面算一下
但是如果定义F[ij[j]表示选第i个了剩下j的方案数的话 好像转移不了
那我们想一想 可不可以写成F[i][j]表示选第i个 给j的数量给它去mod 最大的数是什么? 这样好像可以转移了 j%A[i]->j
然后的话就用G[i][j]表示选最大的数的方案数咯 记住 如果放在后面的话有(i-1)种放法,放在之前每一个数的后面 因为都没关系
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define Maxn 1010
using namespace std;
typedef long long LL;
const LL Mod=**(<<)+;
LL N,X; LL A[Maxn];
LL F[Maxn][]; LL G[Maxn][];
int main()
{
scanf("%lld%lld",&N,&X);
for(LL i=;i<=N;i++) scanf("%lld",&A[i]); sort(A+,A+N+);
memset(F,,sizeof(F)); memset(G,,sizeof(G));
for(LL i=;i<=X;i++) F[][i]=i%A[],G[][i]=;
for(LL i=;i<=N;i++)
{
for(LL j=;j<=X;j++)
{
if(F[i-][j%A[i]]>F[i-][j]) F[i][j]=F[i-][j%A[i]];
else F[i][j]=F[i-][j]; if(F[i][j]==F[i-][j]) G[i][j]=(G[i-][j]*(i-)+G[i][j])%Mod;
if(F[i][j]==F[i-][j%A[i]]) G[i][j]=(G[i-][j%A[i]]+G[i][j])%Mod;
}
}
return printf("%lld\n%lld\n",F[N][X],G[N][X]),;
}
/*
2 15
7 10
*/
[DP之普通系列]的更多相关文章
- 树形DP水题系列(1):FAR-FarmCraft [POI2014][luogu P3574]
题目 大意: 边权为1 使遍历树时到每个节点的时间加上点权的最大值最小 求这个最小的最大值 思路: 最优化问题 一眼树形DP 考虑状态设立 先直接以答案为状态 dp[u] 为遍历完以u为根的子树的答案 ...
- 收集一些关于OI/ACM的奇怪的东西……
一.代码: 1.求逆元(原理貌似就是拓展欧几里得,要求MOD是素数): int inv(int a) { if(a == 1) return 1; return ((MOD - MOD / a) * ...
- To Do List
妈呀...发现不发博文公布自己要学的东西压力少太多了.......... 然后就会变得颓废..................... 求大家监督QAQ....To Do List是近3天左右目标,3天 ...
- Android 4学习(3):概述 - Resources
在应用程序中,处理与代码逻辑无关资源的最佳实践是将其放到程序的外部,典型的资源包括字符串,图片等.Android中的资源文件都在res文件夹中,这些资源包括字符串,颜色,主题,样式,图画,布局,动画, ...
- BUUCTF-writeup
Reverse RSA 使用openssl模块 rsa -pubin -text -modulus -in pub.key得到n值,在 factordb.com上分解大素数得到p,q值,脚本生成pri ...
- hdu ---(4517)小小明系列故事——游戏的烦恼(Dp)
小小明系列故事——游戏的烦恼 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)To ...
- HDU 4539郑厂长系列故事――排兵布阵(状压DP)
HDU 4539 郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 //#pragma co ...
- acdream 小晴天老师系列——苹果大丰收(DP)
小晴天老师系列——苹果大丰收 Problem Description 小晴天的后花园有好多好多的苹果树,某天,苹果大丰收~小晴天总共摘了M个苹果,我们假设苹果之间是不可分辨的. 为了保存苹果,小晴天买 ...
- hdu 4540 威威猫系列故事——打地鼠 dp小水题
威威猫系列故事——打地鼠 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total ...
随机推荐
- Linux环境进程间通信(三):消息队列
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- Google Adsense(Google网站联盟)广告申请指南
Google AdSense 是一种获取收入的快速简便的方法,适合于各种规模的网站发布商.它可以在网站的内容网页上展示相关性较高的 Google 广告,并且这些广告不会过分夸张醒目.由于所展示的广告同 ...
- SOCKET网络编程细节问题1
SOCKET网络编程快速上手(二)——细节问题(1) 三.细节问题一个也不能少 Socket编程说简单也简单,程序很容易就能跑起来,说麻烦还真是麻烦,程序动不动就出问题.记得刚开始写网络代码的时候,那 ...
- 最小堆实现优先队列:Python实现
最小堆实现优先队列:Python实现 堆是一种数据结构,因为Heapsort而被提出.除了堆排序,“堆”这种数据结构还可以用于优先队列的实现. 堆首先是一个完全二叉树:它除了最底层之外,树的每一层的都 ...
- MySQL中函数、游标、事件、视图
MySQL中函数.游标.事件.视图基本应用举例(代码) MySQL中function用户自定义函数c,fun,fun是面向过程的实现方式只能传入参数,或不传入参数,不能传出参数,必有返回值函数中是不能 ...
- TOGAF架构内容框架之内容元模型(下)
TOGAF架构内容框架之内容元模型(下) 2.2 治理扩展(Governance Extensions) 治理扩展元模型内容 治理扩展部分的意图在于引入额外的,并且与支持运营治理的目标和业务服务相关的 ...
- 移动收入超PC端 盛大文学战略转型初见成效
随着智能手机和平板电脑的普及,越来越多的互联网服务也开始向移动端拓展,除了传统的互联网服务如搜索.即时通信之外,网络文学这项新兴的互联网业务也没忽视对移动端的布局. 7月9日,中国最大的网络文学出版平 ...
- 使用ServletContextListener和HttpSessionListener两种监听器实现记录当前网站在线人数
web.xml中配置: <listener> <listener-class>com.mcm.listener.ServletContextListenerImpl< ...
- 国外大师给PHP初学者的8条建议
学习一门新语言可能会是一件很艰巨的任务,最好的办法就是借鉴前辈的经验已达到事半功倍,下面就是为php新手们准备的一些经验餐. 1.从OOP开始Naramore是SourceForge员工以及PHPWo ...
- install cuda5 on ubuntu12.04
1. sudo apt-get install libglapi-mesa 2. sudo apt-get install freeglut3-dev build-essential libx11-d ...