6.25考试整理:江城唱晚&&不老梦&&棠梨煎雪——题解
按照旧例,先安利一下主要作者:一扶苏一 以及扶苏一直挂念的——银临姐姐:银临_百度百科 (滑稽)
好哒,现在步入正题:
先看第一题:
题解:
在NOIP范围内,看到“求方案数”,就说明这个题是一个计数问题。数据范围小的时候一般用DP/递推,数据范围大了的话一般就是数学问题的(组合数学警告)。如果这道题用DP的话,状态即为:dp[i][j]表示第i盆花摆到第j个空的方案数。状态转移方程即为:dp[i][j]=∑dp[i-1][k],k=2*(i-2)+1,...,j-2;时间复杂度为O(n2m)。最终答案即为dp[i]的所有情况再乘上A(m,m)(因为花的顺序也会影响到方案数)。
考虑优化,发现dp[i][j]是由若干个连续的dp[i-1]的和得到,自然想到了前缀和优化,设s[i][j]=dp[i][1]+dp[i][2]+...+dp[i][j],则状态转移方程可以改写为dp[i][j]=s[i-1][j-2]-s[i-1][2*(i-2)],这样就可以用O(1)的复杂度推出来状态了。而s则可在每次dp[i]都算完后推出,时间复杂度O(m),那么整体的时间复杂度即为O(nm)。发现状态的复杂度就是O(nm),显然该DP的复杂度优化下限就是O(nm)(因为复杂度不可能比状态数还少啊),即DP已经优化到尽头了,然而并不足以解出这道题,所以接下来还得考虑一下用数学怎么做了。
我们将m盆花放在n个位置中,还有n-m个空位置,由于m盆花要求互不相邻,所以我们要将这m盆花插到n-m个空位置隔出来的n-m+1个空中(之间的n-m-1个空,还有两边的两个空)。看下图感性理解一下吧(滑稽):
所以最后的答案就是C(n-m+1,m)*A(m,m)=A(n-m+1,m),别忘了计算过程中间及最后要取模。
思路就讲完啦,看标程吧:
#include <stdio.h> int main() {
freopen("ilove.in", "r", stdin);
freopen("ilove.out", "w", stdout);
int I, love, yin, lin;//???
scanf("%d%d%d%d", &I, &love, &yin, &lin);
love = love - yin + ;
int ans = ;
for (int i = love - yin + ; i <= love; ++i) {
ans = 1ll * ans * i % lin;
}
printf("%d\n", ans);
return ;
}
(看到这么短的代码,再看自己考试时2个小时半低效率半走神地推导DP,呵呵~~)
再看第二题:
题解:注意到扶苏行走的规则是:“当扶苏在点u时,扶苏要么在u的孩子中选择一个没有到达过的点v并行走到v,要么选择回到u的家长节点”,这一规则导致扶苏必须一次性的把一个点的子树全部走完后才能从这个点出去,否则就不能再下到子树中没有走过的点了,导致有点没有放上石子,不和题意。由此就知道应从儿子推向父亲的策略。
同时易知一个省石子的策略是将一个节点的儿子都放上石子后,给这个节点放上石子,然后再把他儿子上的所有石子拿走,去向别的节点放石子。同时还发现,一个节点u的一个儿子v放完石子后可以将这个儿子的儿子们上的石子都拿走,去给这个v的兄弟节点放石子,显然这提醒我们呢,很可能要制定一个合理的贪心顺序去依次处理一个节点的所有儿子。
设每个节点u的答案为ansu,走完节点 u 的所有孩子 v 所需要的总石子数 c u;走完所有孩子后,剩下的石子(也就是cu的减去儿子们总的w)为 ret(rest缩写),当 ret ≥ w u的时候,直接用 ret 放下 要在u 放上的石子,于是在节点 u 的放石子总花费就是 c u ,越小越好;当 ret < w u 的时候,用剩下的石子放在 u 上,然后再额外放上去一些石子,这样做的花费是 w u +∑w v,显然是最小的花费,考虑当 c u 越小 ret 才越小,c u 取最小时显然能取到最优情况。综上,可以尽可能使 c u 减小,来达到最优解。这就是贪心所要达到的目的。
那么问题变成了:
有 x 个商品,购买第 i 个物品需要手里有 ans i 元钱,花费 w i 元。求一个顺序
使得购买所有商品所需要的钱数最少。
这个问题的最最优顺序是按照 ans i -w i 不升序购买,也就是差值越大越要先买。
考虑证明:
设有两个物品 i,j,设 a i =ans i -w i ,a j =ans j -w j 。且 a i >a j 。考虑先买 i 再买 j 的
花费是 max(ans i , w i +ans j ) ----1式,同理先买 j 的花费是 max(ans j , w j +ans i )----2式 。
提出 w,则 1式=w i +max(a i ,ans j ),2式=w j +max(a j ,ans i )=w j +max(a j ,a i +w i )=w j +a i +w i 。
考虑 1 式的 max 如果取前面一项,则 1式=w i +a i <2式,如果取后面一项则 1
=w i +ans j =w i +a j +w j <2,于是无论怎么取,1式恒小于2式,于是先买 i 更优。数学归
纳可得按照 ans i -w i 不升序购买最优。于是按照这个顺序,对儿子排一遍序即可。
见标程:
#include <cstdio>
#include <vector>
#include <algorithm> const int maxn = ; int n;
int MU[maxn], ans[maxn];
std::vector<int>son[maxn];//动态数组 void dfs(const int u);
bool cmp(const int &_a, const int &_b); int main() {
freopen("yin.in", "r", stdin);//文件操作
freopen("yin.out", "w", stdout);
scanf("%d", &n);
for (int i = , x; i <= n; ++i) {
scanf("%d", &x);
son[x].push_back(i);
}
for (int i = ; i <= n; ++i) {
scanf("%d", MU + i);
}
dfs();
for (int i = ; i < n; ++i) {
printf("%d ", ans[i]);
}
printf("%d\n", ans[n]);
return ;
} void dfs(const int u) {
for (auto v : son[u])//等价于for(int v=0;v<son[u];v++)
//注意动态数组下标从0开始
{
dfs(v);//深搜每个儿子
}
std::sort(son[u].begin(), son[u].end(), cmp);
int _ret = ;
for (auto v : son[u]) {
if (_ret >= ans[v]) {
_ret -= ans[v];
} else {
ans[u] += ans[v] - _ret;
_ret = ans[v] - MU[v];
}
}
ans[u] += std::max(, MU[u] - _ret);
} inline bool cmp(const int &_a, const int &_b) {
return (ans[_a] - MU[_a]) > (ans[_b] - MU[_b]);//剩下多的在前面
}
终于到最后一题啦:
题解:因为是要求字符串k去匹配一个区间里的所有字符串,所以可以记录一下一个区间中的字符串每位的情况:是否全为0或全为1。对于问号,既可以把他看作0,也可以把他看作1。我们一位一位从前往后看,设当前k的可行情况有ans种。如果在这个区间里当前第w位既可以全是1又可以全是0(即全是问号),那么ans<<=1(相当与ans*=2。为什么要*2?因为k的第w位有两种情况:0或1,由乘法原理知要*2。)若全是0,则ans不变;若全是1,则ans也不变;若既一定有1又一定有0,显然k是不能匹配他们了,就让ans=0,直接break掉。
见到大数据的区间维护与询问,而且维护的信息不是常规维护的信息,就该想到线段数这一数据结构了。(基本查询贼多的题都是数据结构题 ————by 一扶苏一)对每一位,我们都建一个线段数进行维护,由于最多只需建30个不大的线段数,并不会爆空间。(头一次建这么多线段数,真是有点吓人)时间复杂度O(nq logm)(世界上没有什么事情是开一棵线段树不能解决的。如果有,那就开 30 棵——by 一扶苏 一)(但是开30棵线段树还是会TLE的说)。对于最后一个子任务,还是需要再优化一下。注意到n最大30,可以考虑状压。对每个线段树节点可以维护一个longlong型,long long 共有64个二进制位,每2个二进制位去确定一个字符串位,01代表确定全是0,10代表确定全是1,11代表确定既可以是1又可以是0,00代表都不可以。线段树维护时只要按位与就行,维护完毕后在O(n)扫一遍long long 出答案。时间复杂度O(nq + qlogm),就能AC这个题了。思路这么清楚,想必代码也能打出来了吧。把想法用代码实现出来,正是一个合格的OIer要锻炼的品质哟~。
最后在总结一下考试的小技巧:
有关大样例输出的比较,用肉眼看真是麻烦,有没有能让计算机来告诉我们是否一样的方法?有!只要在相应目录下按shift加鼠标右键,打开命令行,用fc命令对比两个文件就行了。有时fc不靠谱,就要自己写一个比较程序。
不要眼高手低,部分分能拿下来也是很好的。也就是说,对于不同的数据范围,我们可以应用不同的算法来拿分。为了避免重名的麻烦,可以定义若干个命名空间,还方便赋予意义。
最后就是交程序前一定要把注释去掉后再编译一遍,确保加文件后不会有因手残RE等被广大OIer痛恨的问题。
6.25考试整理:江城唱晚&&不老梦&&棠梨煎雪——题解的更多相关文章
- 【6.24校内test】T1 江城唱晚
[题目背景] 墙角那株海棠,是你种下的思念. 生死不能忘,高烛照容颜. 一曲江城唱晚,重忆当年坐灯前, 青衫中绣着你留下的线. ——银临<江城唱晚> [问题描述] 扶苏是个喜欢一边听古风歌 ...
- 模拟赛DAY 2 T1江城唱晚
[题目背景] 墙角那株海棠,是你种下的思念. 生死不能忘,高烛照容颜. 一曲江城唱晚,重忆当年坐灯前, 青衫中绣着你留下的线. ——银临<江城唱晚> [问题描述] 扶苏是个喜欢一边听古风歌 ...
- zay大爷的膜你题 D2T1 江城唱晚
依旧是外链... 这一次网易云爆炸了....所以我决定后面的都用QQ 下面是题面 这道题是一道傻逼题 数学题,我们仔细看一看,首先有m朵花的话,我们就有m!种排列方式(也就是m的全排列), 然后我们假 ...
- 6.20校内考试整理——大美江湖&&腐草为萤&&锦鲤抄题解
先安利一下题目作者:一扶苏一 先看第一题: 这道题就是一道简单的模拟题,只要不管一开始的位置,模拟移动与格子对应的触发事件就行了.话不多说,看代码: #include<iostream> ...
- 【6.24校内test】T2 不老梦
[题目背景] 于万人中万幸得以相逢,刹那间澈净明通. 成为我所向披靡的勇气和惶恐,裂山海,堕苍穹. 爱若执炬迎风,炽烈而哀恸,诸般滋味皆在其中. 韶华宛转吟诵,苍凉的光荣,急景凋年深情难共. ——银临 ...
- 模拟赛DAY 2 T2不老梦
[题目背景] 于万人中万幸得以相逢,刹那间澈净明通. 成为我所向披靡的勇气和惶恐,裂山海,堕苍穹. 爱若执炬迎风,炽烈而哀恸,诸般滋味皆在其中. 韶华宛转吟诵,苍凉的光荣,急景凋年深情难共. ——银临 ...
- 2019.2.25考试T3, 离线+线段树
\(\color{#0066ff}{题解}\) #include<bits/stdc++.h> #define LL long long LL in() { char ch; LL x = ...
- 2016.11.6 night NOIP模拟赛 考试整理
题目+数据:链接:http://pan.baidu.com/s/1hssN8GG 密码:bjw8总结: 总分:300分,仅仅拿了120份. 这次所犯的失误:对于2,3题目,我刚刚看就想到了正确思路,急 ...
- 2016.10.29 NOIP模拟赛 PM 考试整理
300分的题,只得了第三题的100分. 题目+数据:链接:http://pan.baidu.com/s/1o7P4YXs 密码:4how T1:这道题目存在着诸多的问题: 1.开始的序列是无法消除的( ...
随机推荐
- 使用docker compose 构建多个镜像
定义docker compose version: ' services: composedb: image: mysql/mysql-server container_name: composedb ...
- C语言I-博客作业05
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 C语言1博客作业05 我在这个课程的目标是 学会运用函数编代码 这个作业在那个具体方面帮助我实现目标 写C语言作业的时候,编代码的实践中 ...
- Linux 查看CPU 核数 还有 CPU 个数的命令
cat /proc/cpuinfo | grep 'physical id' | sort | uniq | wc -l 个数 cat /proc/cpuinfo | grep 'process' | ...
- 大数据平台CentOS7+CDH5.12.1集群搭建
1.CM(Cloudera Manager)介绍 1.1 简介 Cloudera Manager是一个拥有集群自动化安装.中心化管理.集群监控.报警功能的一个工具,使得安装集群从几天的时间缩短在几个小 ...
- restful风格详解
一.概念 RESTful架构,就是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. REST这个词,是Roy Thomas Fielding在他 ...
- C++中的函数重载分析(一)
1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...
- 有序无序ul->li ol->li菜单,默认点击当前弹出下拉,再次点击收起下拉菜单
实现这一效果利用css和js技术结合 以ul->li为例子 <!DOCTYPE html><html lang="en"><head> & ...
- pthread.h 的 undefined reference to `pthread_create'
在编译中要加 -lpthread或-pthread参数(不同版本的gcc可能不一样,man gcc可以查阅对应参数). 例如:在加了头文件#include <pthread.h>之后执行 ...
- pycharm链接数据库以及连接时候出现错误的集合
1.pycharm如何直接连接数据库? 作用:这是一种管理数据库的方式而已,因为在开发过程中结合使用还是不错的!当然,还有有很多管理数据库的工具和方法. 比如:navicat工具 1.1 如何找到管 ...
- vue.js-vuex深入浅出
1:正确的创建目录 2:action.js 异步请求数据 3:index.js 文件声名 4:mutation.js 同步事务 修改state中的值 5:state.js 申明和保存变量或对象 6:如 ...