2016 10 27 考试 dp 向量 乱搞
[TOC]
#20161027考试
#####考试时间 7:50 AM to 11:15 AM
据说这是一套比较正常的考卷,,,嗯,,或许吧,
而且,,整个小组其他人的分数加起来也不如apt123大神多,,
最终,3道题一共30分滚粗
T1:
树形dp题目,感觉我这种dp渣渣是想不出方程了,,%%%%一下apt大神,,
正解:
设dp[i][j]表示根节点为i,距离i最近的被选点的距离大于等于j时的最大节点数,dp[i][0]即为答案
转移:
设f[i][0] = a[i],表示选了a[i]后的初始状态,转移方程为:
dp[i][j] = max(dp[i][j] + dp[son[i]][max(k - j, j - i)], dp[i][max(k - j + 1, j)] + dp[son[i]][j - 1]); j = 1 -> k
dp[i][j] = max(dp[i][j], dp[i][j+1]);
考虑方程,显然设置状态时并没有考虑到同一个根的不同儿子之间的冲突情况,所以必须在转移时候加以限制。
当j的值足够大时,该根节点的j层儿子之间一定不会发生矛盾,因此可以由dp[son[i]][j-1]向dp[i][j]转移
当j的值比较小时,同层的子节点会发生冲突,那么就必须手动解决冲突,即将其中一个点设为k-j,以保证两个子节点之间的距离大于k
再考虑dp方程本身的含义,显然可知对于dp[i][j],随着j变小可选择的范围应逐渐增多,即如果dp[i][3] = 4,dp[i][1]最少为4,由此,再转移后再加入dp[i][j] = max(dp[i][j], dp[i][j+1])
#include <cstdio>
#include <algorithm>
#include <cstring>
using std :: max;
const int maxn = 20000 + 100;
int last[maxn], pre[maxn], other[maxn];
int f[maxn][120];
int n, k;
int a[maxn];
int tot = 0;
int x1, x2;
void add(int x, int y) {
tot++;
pre[tot] = last[x];
last[x] = tot;
other[tot] = y;
}
void dfs(int x, int from) {
f[x][0] = a[x];
for (int p = last[x]; p; p = pre[p]) {
int q = other[p];
if (q == from) continue;
dfs(q, x);
f[x][0] = f[x][0] + f[q][k];
for (int j = 1; j <= k; j++) {
f[x][j] = max(f[x][j] + f[q][max(k - j, j - 1)], f[x][max(k - j + 1, j)] + f[q][j-1]);
}
}
for (int i = k-1; i >= 0; i--) f[x][i] = max(f[x][i+1], f[x][i]);
}
int main () {
freopen("score.in", "r", stdin);
freopen("score.out", "w", stdout);
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i < n; i++) {
scanf("%d %d", &x1, &x2);
add(x1, x2);
add(x2, x1);
}
dfs(1, 0);
printf("%d", f[1][0]);
return 0;
}
再贴上apt大犇的AC代码,代码略长但更为直观
var
n,m,a,b,bg :longint;
f :array[0..10010,0..105]of longint;
pre,oth,last,q,w :array[0..20010]of longint;
vis :array[0..10010]of boolean;
ii,i,j,k,p,r :longint;
totl,ans,ret,mxs :longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a); exit(b);
end;
procedure conn(a,b:longint);
begin
inc(totl);
pre[totl]:=last[a];
last[a]:=totl;
oth[totl]:=b;
end;
procedure bfs;
var p,cur,r,he,ta:longint;
begin
he:=0; ta:=1; q[1]:=1; vis[1]:=true;
while he<>ta do begin
inc(he);
cur:=q[he];
p:=last[cur];
while p>0 do begin
r:=oth[p];
if not vis[r] then begin
vis[r]:=true;
inc(ta);
q[ta]:=r;
end;
p:=pre[p];
end;
end;
end;
begin
assign(input,'score.in'); reset(input);
assign(output,'score.out'); rewrite(output);
read(n,m);
for i:=1 to n do read(w[i]);
for i:=1 to n-1 do begin
read(a,b);
conn(a,b); conn(b,a);
end;
bfs;
bg:=(m>>1)+1;
for ii:=n downto 1 do begin
i:=q[ii];
f[i,0]:=w[i];
p:=last[i];
while p>0 do begin
r:=oth[p];
inc(f[i,0],f[r,m]);
p:=pre[p];
end;
for k:=m downto bg do begin
f[i,k]:=f[i,k+1];
ret:=0;
p:=last[i];
while p>0 do begin
r:=oth[p];
inc(ret,f[r,k-1]);
p:=pre[p];
end;
f[i,k]:=max(f[i,k],ret);
//if (k=3)and(i=1) then writeln('??',ret,' ',f[3,2],' ',f[i,k]);
end;
for k:=bg-1 downto 1 do begin
f[i,k]:=f[i,k+1];
ret:=0; mxs:=0;
p:=last[i];
while p>0 do begin
r:=oth[p];
inc(ret,f[r,m-k]);
p:=pre[p];
end;
p:=last[i];
while p>0 do begin
r:=oth[p];
f[i,k]:=max(f[i,k],ret-f[r,m-k]+f[r,k-1]);
p:=pre[p];
end;
{if (k=2)and(i=1) then writeln('??',ret,' ',mxs,' ',f[2,1]);
f[i,k]:=max(f[i,k],f[mxs,k-1]+ret-f[mxs,m-k]); }
end;
f[i,0]:=max(f[i,0],f[i,1]);
end;
{for i:=1 to n do begin
for j:=0 to m do begin
write(f[i,j],' ');
end;
writeln;
end; }
for i:=0 to m do
ans:=max(ans,f[1,i]);
write(ans);
close(input);
close(output);
end.
T2:
线性dp,状态定义和转移都比较邪,,,
考试时把题目理解成处理玉的方案数,导致前期思路错误,未能完成题目
正解:
F[i]表示到了第i天恰好第一次出现k个连续的晴天的方案数,那么要保证i-k这一天一定是雨天或者X,于是i-k+1i这一段的天气已经全部被固定了,可以得出方案数有2^(1i-k中X的个数),然后减去所有不合法的状态,对于Fj就减去F[j]2^(j+1~i-k中X的个数)(可以记一个数组t1,每次遇到X就2,每次都加上F[i]的值),(j>i-k)的就是减去F[j],对于雨天反过来做一次,最后答案是sigma(F[i]*雨天的t1[i+1])
实现:
使用numx, numw, numb记录每种天气出现的次数,为方便期间,numx, numb 从1开始,numw从n逆向开始
转移
当题设条件满足时,f[i] = 2 ^ (numx[i-k-1]) - t[i - k - 1], ts[i] = (ts[i-1]) * (1 + (当前为x) ) + f[i]。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int mod = 1000000007;
const int maxn = 1000000 + 100;
int n, k;
char s[maxn];
long long pow2[maxn];
int numb[maxn], numw[maxn], numx[maxn];
long long fs[maxn], fr[maxn], ts[maxn], tr[maxn];
int main () {
freopen("jade.in", "r", stdin);
freopen("jade.out", "w", stdout);
scanf("%d %d", &n, &k);
scanf("%s", s + 1);
s[0] = 'X';
s[n+1] = 'X';
pow2[0] = 1;
for (int i = 1; i <= n; i++) pow2[i] = (pow2[i-1] * 2) % mod;
for (int i = 1; i <= n; i++) numb[i] = numb[i-1] + (s[i] == 'B');
for (int i = n; i >= 1; i--) numw[i] = numw[i+1] + (s[i] == 'W');
for (int i = 1; i <= n; i++) numx[i] = numx[i-1] + (s[i] == 'X');
for (int i = k; i <= n; i++) {
if ((numb[i] - numb[i-k] + numx[i] - numx[i-k]) == k && s[i-k] != 'B')
fs[i] = ((pow2[numx[i - k - 1]] - ts[i - k - 1]) + mod) % mod;
ts[i] = (ts[i-1] * (1 + (s[i] == 'X')) + fs[i]) % mod;
}
numx[n+1] = numx[n];
for (int i = n - k + 1; i >= 1; i--) {
if (numw[i] - numw[i + k] + numx[i + k - 1] - numx[i - 1] == k && s[i + k] != 'W')
fr[i] = ((pow2[numx[n] - numx[i + k]] - tr[i + k + 1]) + mod) % mod;
tr[i] = ( tr[i + 1] * (1 + (s[i] == 'X')) + fr[i] ) % mod;
}
long long ans = 0;
//for (int i = 1; i <= n; i++) printf("%I64d ", ts[i]);
for (int i = 1; i <= n; i++) ans = ((ans + fs[i] * tr[i + 1] % mod) + mod) % mod;
printf("%I64d", ans);
return 0;
}
具体细节有待进一步讨论
具体细节有待进一步讨论
具体细节有待进一步讨论
具体细节有待进一步讨论
T3:
正在写。。。
2016 10 27 考试 dp 向量 乱搞的更多相关文章
- 2016 10 28考试 dp 乱搞 树状数组
2016 10 28 考试 时间 7:50 AM to 11:15 AM 下载链接: 试题 考试包 这次考试对自己的表现非常不满意!! T1看出来是dp题目,但是在考试过程中并没有推出转移方程,考虑了 ...
- CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))
题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...
- POJ 3671 DP or 乱搞
思路: 1.DP f[i][j]:前i个数 最后一个数是j的最小花费 f[i][j]=min(f[i][j],f[i-1][k]+(a[i]!=j));1<=k<=j 这种做法比较有普遍性 ...
- 2016 10 26考试 NOIP模拟赛 杂题
Time 7:50 AM -> 11:15 AM 感觉今天考完后,我的内心是崩溃的 试题 考试包 T1: 首先看起来是个贪心,然而,然而,看到那个100%数据为n <= 2000整个人就虚 ...
- hdu4714树形DP+贪心(乱搞)
Tree2cycle A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...
- angular2 组件之间通讯-使用服务通讯模式 2016.10.27 基于正式版ng2
工作中用到ng2的组件通讯 奈何官方文档言简意赅 没说明白 自己搞明白后 整理后分享下 rxjs 不懂的看这篇文章 讲很详细 http://www.open-open.com/lib/view/ope ...
- uoj#267. 【清华集训2016】魔法小程序(乱搞)
传送门 感觉很像FFT的过程的说-- 先来考虑\(b\)如何转化成\(c\),那么只要通过它的逆过程就可以了 首先,我们称"魔法"为比较两个数的字典序,记\(x=a_0\),那么把 ...
- 2021.10.27考试总结[冲刺NOIP模拟17]
T1 宝藏 发现每个数成为中位数的长度是关于权值单调的.线段树二分判断是否合法,单调指针扫即可. 考场上写了二分,平添\(\log\). \(code:\) T1 #include<bits/s ...
- My latest news (--2016.10)
2016.10.31 22:44 一个“程序”,打代码占40%.思考占60% 2016.10.30 20:53 周末,话说今天有晚上讲座,还点名,了,悲催.之前学习的Qt有点问题,悲催.推荐个博文:h ...
随机推荐
- BZOJ 4006 [JLOI2015]管道连接(斯坦纳树+子集DP)
明显是一道斯坦纳树的题. 然而这题只需要属性相同的点互相连接. 我们还是照常先套路求出\(ans[s]\). 然后对\(ans[s]\)做子集DP即可. 具体看代码. #include<iost ...
- vivo输入法 需求分析
我使用的输入法:vivo输入法 1,用户界面:界面为白色和灰色,整体简洁大方,个人而言外观挺不错.但是不能自定义界面,更改背景图片或是主题. 2,记住用户选择:可记忆上次使用后的键盘方式(26键或是9 ...
- 再识Quartz
在之前的项目中使用过Quartz,但都是基于XML配置定义任务的.目前一个项目应用需要对任务进行创建.暂停.删除等动态管理.所以再次在网上翻了翻,再来好好重新认识下Quartz. 名词解释: sche ...
- java实现支付宝电脑支付(servlet版本)
前期准备: 蚂蚁金融开放平台 进行登录操作 进入我的开放平台 在上方找到沙箱,进入沙箱(网络编程虚拟执行环境). 这里的RSA2密钥设置下,我已经设置好了,所以便有了支付宝公钥(公钥是对外公开的,私钥 ...
- vue解决跨域问题
vue解决跨域问题 vue跨域解决方法和小总结 vue项目中,前端与后台进行数据请求或者提交的时候,如果后台没有设置跨域,前端本地调试代码的时候就会报“No 'Access-Control-Allow ...
- 洛谷 P2298 Mzc和男家丁的游戏
P2298 Mzc和男家丁的游戏 题目背景 mzc与djn的第二弹. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过上一弹的都知道).他把她们召集在了一起,他们决定玩捉迷藏.现在mzc要来 ...
- jquery简直是太酷炫强大了
链接地址:http://www.yyyweb.com/350.html Web 开发中很实用的10个效果[源码下载] 小鱼 发布于 3年前 (2014-07-15) 分类:前端开发 阅读(303741 ...
- 保留全部Android crash信息
保留全部Android crash信息 framework/base/core/java/com/android/internal/os/RuntimeInit.java 又一次以下这个函数,增加自己 ...
- Android生命周期里你也许不知道的事
Android生命周期预计连刚開始学习的人都再熟悉只是的东西了,但这里我抛出几个问题.也许大家曾经没有想过或者可能认识的有些错误. 一.当A启动B时,A和B生命周期方法运行的先后顺序是如何的?当按返回 ...
- linux centos下载地址
Centos下载地址 http://r.aminglinux.com