看到Day 2的题真的想打死zay了,忒难了QwQ~

T1 江城唱晚

这明显是个求方案数的计数问题,一般的套路是DP和组合数学。

正如题目中所说,这个题是一个 math 题。      ----zay不会的 math 题让我们做?QwQ

DP已经优化到了尽头,现在我们考虑组合数学!

zhx:这应该是个小学奥数题!

恩,这其实就是个经典的组合数问题啦。

首先我们以数学的来思考这个题:

我们有n个位置来摆放m盆花,还要保证每盆花之间至少有一个空位置。如果我们单单去刻意拆空位置的话,我们会发现这很难实现,那怎么简单得去保证每两盆花之间有空位置呢?

回忆起了当时做这种题的思路:先让每盆花之间插一个空位置!

什么意思呢?

就像这样,我们先让m盆花之间每盆花都相隔一个空位置(下划线_ 代表的是空位置):

这样我们就预先将m盆花放好了,还占了(m-1)个空位置,So我们还有 n - m - (m -1 )=n - 2 * m +1 个空位置;

所以我们接着将这 n - 2 * m + 1 个空位置随便往里边差不就能产生所有的情况了嘛?

只不过要注意我们是将 (n - 2 * m + 1)个空位置往(m + 1)个空里插,求方案数!因为注意到第1盆花左边和第m盆花右边也可以插入空位置。

然后我们再看一个公式:

将x个球放进y个盒子里的方案数:

球同,盒不同,盒可以为空   C(x+y-1, y-1)

解释一下为什么是这样:

看到我们的原问题:将(n - 2 * m + 1)个空位置往(m + 1)个空里边插,就可以抽象的看成:将(n - 2 * m + 1)个小球放进(m + 1)个盒子里,然后求方案数;

其中每一个空位置是一样的,但是插到哪个空却是不同的,并且每两盆花之间可以不再插空位置(因为之前我们已经在每两盆花之间插了一个空位置,所以这时候这两盆花的空位置数就是1)

至于为什么公式是这样……,找度娘鸭QwQ~!

显然对于这个题,x = n - 2 * m + 1,y = m + 1,我们代入公式就是:C(n - m + 1,m);   // C的下标对应的是括号左部分,C的上标对应的是括号右部分

再找度娘找到了求组合数的公式:   

那么:

因为花盆的编号不同也算是不同的方案,而所有花的编号的不同方案数是 ,所以我们将这两部分乘起来就是答案!

细心的同学会发现正好可以将m!约掉,所以最后的答案就是:

其实这里求最后答案也是有技巧滴(好像只能这么求吧),我们知道x!是从1乘到 x,那么对于这两个阶乘是有公共部分的!

∵ n - m + 1 > n - 2 * m + 1

∴(n - m + 1)!包含(n - 2 * m + 1)!,即(n - 2 * m + 1)! |  (n - m + 1)!

∴ (n - m + 1)!

= 1 * 2 * 3 * …… * (n - 2 * m + 1)* (n - 2 * m + 2)* …… *(n - m)*(n - m + 1)

=(n - 2 * m + 1)!*(n - 2 * m + 2)* …… * (n - m)*(n - m + 1)

(n - m + 1)!/(n - 2 * m + 1)!=(n - 2 * m + 2)*(n - 2 * m + 3)* …… *(n - m)*(n - m + 1)

最后注意一下乘的过程中不断取模,防止爆long long ;

代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
int read()
{char ch=getchar();int a=0,x=1;while(ch<'0'||ch>'9'){if(ch=='-') x=-x;ch=getchar();}while(ch>='0'&&ch<='9'){a=(a<<3)+(a<<1)+(ch-'0');ch=getchar();}return a*x;
}
int type,n,m,maxn;
long long x,y,mod;
long long jc[5000001];
int main()
{freopen("ilove.in","r",stdin);freopen("ilove.out","w",stdout); type=read();n=read();m=read();mod=read();     //从n个位置里摆m盆花 if(n<2*m-1)                                   //如果n<2*m-1,就不能预先摆好m盆花并且每盆花之间有一个空位置
    {cout<<0;                                  //0种方案 return 0;}jc[1]=1;maxn=max(n,n+m-1);for(int i=2;i<=maxn;i++) jc[i]=jc[i-1]%mod*i%mod;   //求出了1~m的阶乘 if(n==2*m-1)                                   //这时候每盆花之间只可能有一个空位置,那么方案数就是m!
    {printf("%lld",jc[m]);return 0;}    long long ans=1;                              //怕爆int for(int i=n-2*m+2;i<=n-m+1;i++) ans=ans*i%mod;printf("%lld",ans);return 0;
}

一些好像是好像又不是题外话的话:

身为蒟蒻的我当然也推出来了这个公式啦,但是我当时没考虑到有公共部分,我是直接两部分的阶乘相除;按理来说没错是吧(我一开始也不知道自己到底是哪错了,直到jyy大佬给我讲了之后才明白,哎,果然我还是太菜了),但是我却忽略掉最重要的一点:模意义下不能做除法!导致最后输出都是0。

(⊙o⊙)…其实我当时也想到这一点啦,就想方设法求(n - 2 * m + 1)!的逆元:线性?爆空间!费马小定理?不互质也不会求欧拉函数,还可能也爆空间!扩展欧几里得?这个应该可以!QwQ~

然后就写上了扩展欧几里得算法,当时的确忘了怎么写给写炸了,但回头我再改了改,还是有好多点过不去(好像只有当模数是质数的时候才能过去QwQ)

#include<iostream>
#include<cstdio>
using namespace std;
int read()
{char ch=getchar();int a=0,x=1;while(ch<'0'||ch>'9'){if(ch=='-') x=-x;ch=getchar();}while(ch>='0'&&ch<='9'){a=(a<<3)+(a<<1)+(ch-'0');ch=getchar();}return a*x;
}
int type,n,m,maxn;
long long x,y,mod;
long long jc[5000001];
int exgcd(long long a,long long b,long long &x,long long &y)
{if(b==0){x=1;y=0;return a;}exgcd(b,a%b,x,y);int r=x;x=y;y=r-(a/b)*x;
}
int main()
{freopen("ilove.in","r",stdin);freopen("ilove.out","w",stdout); type=read();n=read();m=read();mod=read();     //从n个位置里摆m盆花 if(n<2*m-1) {cout<<0;return 0;}jc[1]=1;maxn=max(n,n+m-1);for(int i=2;i<=maxn;i++) jc[i]=jc[i-1]%mod*i%mod;   //求出了1~m的阶乘 if(n==2*m-1){printf("%lld",jc[m]);return 0;}    int gcd=exgcd(jc[n-2*m+1],mod,x,y);x=(x%mod+mod)%mod;printf("%lld",jc[n-m+1]*gcd%mod*x%mod);return 0;
}

T2 不老梦

测试点 1: 显然直接输出 w1 即可。期望得分 5 分。

测试点 2-5: 爆搜,搜出一个放石子的顺序,然后 O(n) 的 check 是否合法。时间复杂度 O(n!*n)。期望得分 20 分。

测试点 6-7: 注意到根据题目规定的走法,在进入一个节点以后,必须遍历完它的整个子树, 否则一旦离开这个节点,再也无法进入这棵子树,从而导致该节点的某个孩子没能放 上石子,导致这个节点不能放上石子。同时又有每个节点放上石子以后,它的子树的 石子可以全部取回。设在节点 u 放石子需要有 ansu 个石子(ansu=(∑ansk)+wu,k是u的所有孩子),则放完 u 以后可以取回 ansu-wu 个石子。 于是考虑影响问题答案的显然是从 u 进入每个孩子的顺序,由于最多有两个孩 子,直接比较一下就可以知道先进入哪个孩子更优秀了。时间复杂度 O(n),期望得分 10 分。

测试点 8-10: 延续上一组测试点的思路,由于只有最多 5 个孩子,可以直接爆搜选孩子的顺序,看看哪个更优秀。时间复杂度 O(n*x!),其中 x=5。期望得分 15 分。

测试点11-14:由于树高最多三层是吧,那么因为第三层放了之后不能取回石子,所有先放谁无所谓的,关键就是从根结点1出发看看先遍历第二层的哪个儿子结点了;

考虑走完节点 u 的所有孩子 v 所需要的总石子数 cu,显然是越少越好。证明如下:

那么问题变成了: 有 x 个商品,购买第 i 个物品需要手里有 ansi 元钱,花费 wi 元。求一个顺序 使得购买所有商品所需要的钱数最少。

这个问题的最最优顺序是按照 ansi-wi 不升序购买,也就是差值越大越要先买。 考虑证明:

设有两个物品 i,j,设 ai=ansi-wi,aj=ansj-wj。且 ai>aj

考虑先买 i 再买 j 的 花费是多少:

我们买 i 需要ansi;到了买j的时候我们已经取回了ai颗石子(为了少用石子是一定要收回这些石子的),那么我们尽量要用这 ai 颗石子去买 j;考虑到买 j要用ansj,如果ansj<ai,那么我们就不用再花更多的石子了,那么总的花费就是ansi;如果ansj>ai,那么我们还需要添上(ansj-ai)才行,又因为ai=ansi-wi,所以我们要添上(ansj-ansi+wi)才可以买到 j,加上我们一开始买 i 所需要的ansi,那么一共要(ans- ansi+wi)+ansi=ansj+wi,而我们并不知道ans与a的大小关系,所以我们用一个max来表示最多需要花费的石子,那么得出式子: max(ansi, wi+ansj) ①;

同理先买 j 的花费是 max(ansj, wj+ansi) ②。

因为 ai=ansi-wi,aj=ansj-w ,则ans=ai + w,ansj =aj + wj,代入原式提出 w,则 ①=wi+max(ai,ansj),②=wj+max(aj,ansi)=wj+max(aj,ai+wi)=wj+ai+wi。 考虑 ① 式的 max 如果取前面一项,则 ①=wi+ai<②,如果取后面一项则 ① =wi+ansj=wi+aj+wj<②,于是无论怎么取,①式恒小于②式,于是先买 i 更优。数学归纳可得按照 ansi-wi 不升序购买最优。

于是按照这个顺序,排一遍序即可。期望得分 20 分。

测试点 15-20: 可以发现上面的结论同样适用于树高更高的情况,于是在 dfs 回溯的时候对子节 点排序,即可算出该节点的答案,期望得分 30 分。

标程代码:

#include <cstdio>
#include <vector>
#include <algorithm>const int maxn = 100010;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 = 2, x; i <= n; ++i) {scanf("%d", &x);son[x].push_back(i);}for (int i = 1; i <= n; ++i) {scanf("%d", MU + i);}dfs(1);for (int i = 1; i < n; ++i) {printf("%d ", ans[i]);}printf("%d\n", ans[n]);return 0;
}void dfs(const int u) {for (auto v : son[u]) {dfs(v);}std::sort(son[u].begin(), son[u].end(), cmp);int _ret = 0;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(0, MU[u] - _ret);
}inline bool cmp(const int &_a, const int &_b) {return (ans[_a] - MU[_a]) > (ans[_b] - MU[_b]);
}

转载于:https://www.cnblogs.com/xcg123/p/11081202.html

2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解相关推荐

  1. NOIP 模拟赛 长寿花 题解

    NOIP 模拟赛 长寿花 题解 要放 \(n\) 层物品,第 \(i\) 层有 \(a_i\) 个位置放物品,物品有 \(m\) 中颜色,有约束条件: 同一层两个相邻物品颜色不能相同. 相邻两层颜色集 ...

  2. 2019.6.18 校内测试 分析+题解

    话说校内怎么又考试了QwQ,哎考就考吧(随鸡硬便啦) 考试的三个题分别都再洛谷上: P1067 多项式输出  传送门 P1068 分数线划定  传送门 P1069 细胞分裂     传送门 呜呜呜~T ...

  3. 2019.6.28 校内测试 T4 【音乐会】达拉崩吧·上

    考试的一道附加题~ 一看题目描述:把区间[l,r]里每个数异或上x,求区间[l,r]里所有数的异或和,这明显的要用数据结构或RMQ吧. 恩,所以正解就是线段树啦,至于树状数组行与否,不知道~ wate ...

  4. NOIP模拟(10.22)T2 杆子的排列

    杆子的排列 题目背景: 10.22 NOIP模拟作业T2 分析:DP 定义状态dp[i][j][k]表示,目前枚举到第i大的数(即n - i + 1)那么显然如果这一个数放在左边,可以在左边被看到,放 ...

  5. 训练日志 2019.1.24

    今天上午补了两道题,然后转接线到了,就弄了一下扩展显示器,下午打比赛果真爽得很,感觉实验室越来越舒服了...下一步就该搬到实验室住了... 第一道签到题出的比较快,第二道贪心因为没注意数组范围,直接 ...

  6. 计算机单招语文试题,2019年高职单招语文模拟试题

    2019年高职单招语文模拟试题2019-02-21 13:17:22文/叶丹 学校单招的考试形式一般为"文化联考+综合素养测试"相结合的考试模式.文化联考包括语数英三门科目:综合素 ...

  7. 2019学位计算机模拟试题,2019年下半年成人学位英语模拟试题1

    [导语]不积跬步,无以至千里,不积小流,无以成江海.无忧考网整理为大家整理了"2019年下半年成人学位英语模拟试题1",欢迎阅读参考!更多相关讯息请关注无忧考网! 1.You ca ...

  8. 2019年高压电工作业安全生产模拟考试题库及答案

    2019年高压电工作业安全生产模拟考试题库及答案 题库来源:安全生产模拟考试一点通 第1题.[判断题] 三相交流对称电路中,如采用三角形接线时,线电流等于相电流的根号3倍. A.正确 B.错误 正确答 ...

  9. 2019年低压电工作业安全生产模拟考试题库及答案

    2019年低压电工作业安全生产模拟考试题库及答案 题库来源:安全生产模拟考试一点通 第1题.[判断题]10kV以下运行的阀型避雷器的绝缘电阻应每年测量一次. A.正确 B.错误 正确答案:B 第2题. ...

  10. 2019 年(H 题)模拟电磁曲射炮

    2019 年(H 题)模拟电磁曲射炮 2019 年全国大学生电子设计竞赛试题 [本科组] 文章目录 2019 年(H 题)模拟电磁曲射炮 一.任务 二.要求 1 .基本要求 2.发挥部分 三.说明 四 ...

最新文章

  1. 【LDA学习系列】Beta分布Python代码
  2. Android开发之Android Material Design Toolbar自定义随笔
  3. Educational Codeforces Round 81 (Rated for Div. 2) C. Obtain The String 序列自动机
  4. mouseleave mouseout时候悬浮框不应该消失的时候消失了 css 解决办法
  5. Python机器学习:多项式回归与模型泛化006验证数据集与交叉验证
  6. JAVA面向对象OOP多态→抽象类abstract、接口interface实现implement、final不变修饰符、样例代码
  7. tensorflow中slim模块api介绍
  8. 源码分析ElasticJob任务错过机制(misfire)与幂等性
  9. Python实战—CSDN自动登录及评论
  10. 考研——考研有用的“宝贝”(软件,公众号,网站,励志电影,音乐)
  11. 常用z反变换公式表_高中三角函数公式推理amp;记忆
  12. 利用HttpClient4,实现get,post 参数,post json,post file
  13. 服务器CPU使用率过高排查与解决思路
  14. flink任务优化总结
  15. 为什么穷人越穷,富人越富?
  16. python视频转字符详细教程_python视频转字符画教程
  17. 第六周 day6 python学习笔记
  18. 用innobackupex做全量备份
  19. 微信小程序之数据处理
  20. MySQL创建使用数据库

热门文章

  1. python---面向对象实例(烤地瓜、搬家具)
  2. 局域网、以太网、无线局域网学习笔记
  3. 一把互斥锁保护多个资源
  4. MySQL分库分表后聚合查询_MySQL订单分库分表多维度查询
  5. 官方rom提取原签名工具_官方和第三方ROM的提取与分解
  6. 镜头、CCD芯片、视场、物距之间的关系
  7. 各种品牌电脑U盘启动快捷键
  8. 我是如何走进黑客世界的?
  9. 工业视觉 五 频闪及抑制频闪
  10. MacBook外接显示器及相关设置详解(分屏/多屏)