Part.I游记

纪中的电脑真好,开个资源监视器就蓝屏了(插上U盘也有蓝屏)。我。。。 (F**k

纪中的OJ怎么和CCF的这么像?

上午比赛做第一题的时候用并查集判断是否是同一个连通块的时候把并查集写炸了。。。调了一个小时还是放弃了并查集。。。QAQ。。。

又用了一个半小时写第二第三题的代码。。。结果连样例都没过。。。

最后用30分钟狂暴打出第二第三题的骗分代码,总算骗了35分。

考完评测时猛然发现第一题错选的C语言,于是愉快地CE了。。。

成绩不算太理想。。。(好久没做OI,都玩ACM多校赛去了。。。

中午就去吃饭了,纪中人真多却只开一层的食堂(有16个窗口每个窗口前的队伍都从窗口前排到食堂的另一边(至少100人吧))。。。我花了半个多小时去排队。。。

纪中的寝室环境真的好,铁皮门窗(路过自带BGM)+生锈铁床+生锈铁柜+老式座机(打个电话要按半天键)+脏的不能再脏的空调和风扇+永远打不开的阳台灯+长满青苔的洗漱台+总是漏水的洗漱台排水管+暴露在外面长满青苔的下水管道+看着就要断的已经锈掉的铁制晾衣绳+长满青苔的拖帕+不能冲水的厕所+台风。。。连插孔都不提供。。。

(典型的牢狱生活)

我们用了一两个小时才清理干净。。。

欢迎参加大型真人生存体验游戏——寝室风云

Part.II题解

A.水叮当的舞步

题目

题目描述

水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。

为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~

地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。

水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,地毯左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。

由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。

输入

每个测试点包含多组数据。

每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。

接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。

N=0代表输入的结束。

输出

对于每组数据,输出一个整数,表示最少步数。

样例输入

2
0 0
0 0
3
0 1 2
1 1 2
2 2 1
0

样例输出

0
3

数据范围

对于30%的数据,N<=5

对于50%的数据,N<=6

对于70%的数据,N<=7

对于100%的数据,N<=8,每个测试点不多于20组数据。

分析

由于 N N N过小,所以我们考虑搜索。

搜索的每一步暴力枚举当前选择的数字并暴力改变当前连通块颜色,并继续递归。

然而我们不难发现,这样做解答树的深度有点大,所以我们考虑使用IDA*算法解决这个问题。

设计估价函数的时候我们选择利用没在连通块的点中不同颜色的数量。(个人觉得可以用剩下的不同连通块数量来当估价函数)

细节颇多,这里简要提及几个。

我们可以不必暴力修改所有位置的颜色(因为保存变量很耗内存,修改耗时过大且麻烦),我们采用的做法是另开一个vis数组,若vis[i][j]==0表示这个点在当前连通块的外面,vis[i][j]==1表示这个点在连通块内,vis[i][j]==2表示这个点是连通块外且与连通块相连的点。

每次修改只需改变vis就是了。

还有个剪枝:

若当前改变的颜色无法扩大连通块的大小,那么我们应剪掉。

据说加了这个剪枝大爆搜都能过。。。

参考代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;const int Maxn=8;
const int dir[][2]={{0,1},{0,-1},{-1,0},{1,0}};int N,A[Maxn+5][Maxn+5];int vis[Maxn+5][Maxn+5];
//vis[i][j]==1 in
//vis[i][j]==2 surrounding
int H() {bool b[10];int tmp=0;memset(b,false,sizeof b);for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)if(vis[i][j]!=1&&b[A[i][j]]==false) {tmp++;b[A[i][j]]=true;}return tmp;
}
void Color(int x,int y,int col) {vis[x][y]=1;for(int i=0;i<4;i++) {int tx=x+dir[i][0],ty=y+dir[i][1];if(tx<1||tx>N||ty<1||ty>N||vis[tx][ty]==1)continue;vis[tx][ty]=2;if(A[tx][ty]==col)Color(tx,ty,col);}
}
bool check(int col) {int tmp=0;for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)if(vis[i][j]==2&&A[i][j]==col)Color(i,j,col),tmp++;return tmp>0;
}
int maxd;
bool DFS(int depth) {int t=H();if(t==0)return true;else if(depth+t>maxd)return false;int pre_vis[Maxn+5][Maxn+5];memcpy(pre_vis,vis,sizeof vis);for(int i=0;i<=5;i++) {if(check(i))if(DFS(depth+1))return true;memcpy(vis,pre_vis,sizeof pre_vis);}return false;
}int main() {#ifdef LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifwhile(scanf("%d",&N)!=EOF&&N) {for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)scanf("%d",&A[i][j]);maxd=0;Color(1,1,A[1][1]);while(true) {if(DFS(0)) {printf("%d\n",maxd);break;}maxd++;}memset(vis,0,sizeof vis);}return 0;
}

B.Vani和Cl2捉迷藏

题目

题目描述

vani和cl2在一片树林里捉迷藏……

这片树林里有N座房子,M条有向道路,组成了一张有向无环图。

树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。如果从房子A沿着路走下去能够到达B,那么在A和B里的人是能够相互望见的。

现在cl2要在这N座房子里选择K座作为藏身点,同时vani也专挑cl2作为藏身点的房子进去寻找,为了避免被vani看见,cl2要求这K个藏身点的任意两个之间都没有路径相连。

为了让vani更难找到自己,cl2想知道最多能选出多少个藏身点?

输入

第一行两个整数N,M。

接下来M行每行两个整数x、y,表示一条从x到y的有向道路。

输出

一个整数K,表示最多能选取的藏身点个数。

样例输入

4 4
1 2
3 2
3 4
4 2

样例输出

2

数据范围

对于20% 的数据,N≤10,M<=20。

对于60% 的数据, N≤100,M<=1000。

对于100% 的数据,N≤200,M<=30000,1<=x,y<=N。

分析

题解讲到了什么反链,Dilworth定理等等高级玩意。。。不管这些,我们用讲通俗一点。

不难发现这玩意就是个最大独立集问题。

这可以用二分图解决,因为在二分图中最大独立集点数等于最小边覆盖。

但是不难发现有些链是相交的(共用一些点或边),对于这种情况,我们跑一遍Floyd就是了,这样就转换为了不相交的最小边覆盖。

求解这类问题我们需要拆点。

将一个点拆成两个点,一个在 X X X部,另一个在 Y Y Y部。当 u , v u,v u,v相连时,从 X X X部的 u u u向 Y Y Y部的 v v v连一条边。连完后跑一遍最大匹配就是了。最小边覆盖即为总点数减去匹配数。

所以答案就是总点数减去匹配数。

程序中由于我太懒了,懒得去建新图,所以直接在旧图上跑的最小边覆盖。。。(这居然过了!!!)

参考代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;const int Maxn=200;
const int Maxm=30000;int N,M;
bool G[Maxn+5][Maxn+5];bool vis[Maxn*2+5];
int match[Maxn*2+5];
int cnt;
bool DFS(int u) {for(int v=1;v<=N;v++)if(G[u][v]==true&&vis[v]==false) {vis[v]=true;if(match[v]==0||DFS(match[v])) {match[v]=u;return true;}}return false;
}int main() {#ifdef LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifscanf("%d %d",&N,&M);for(int i=1;i<=M;i++) {int u,v;scanf("%d %d",&u,&v);G[u][v]=true;}for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)if(G[i][j]==false&&i!=j)for(int k=1;k<=N;k++)G[i][j]|=(G[i][k]&G[k][j]);int cnt=0;for(int i=1;i<=N;i++) {memset(vis,false,sizeof vis);if(DFS(i))cnt++;}printf("%d\n",N-cnt);return 0;
}

C.粉刷匠

题目

题目描述

赫克托是一个魁梧的粉刷匠,而且非常喜欢思考= =

现在,神庙里有N根排列成一直线的石柱,从1到N标号,长老要求用油漆将这些石柱重新粉刷一遍。赫克托有K桶颜色各不相同的油漆,第i桶油漆恰好可以粉刷Ci根石柱,并且,C1+C2+C3…CK=N(即粉刷N根石柱正好用完所有的油漆)。长老为了刁难赫克托,要求相邻的石柱颜色不能相同。

喜欢思考的赫克托不仅没有立刻开始粉刷,反而开始琢磨一些奇怪的问题,比如,一共有多少种粉刷的方案?

为了让赫克托尽快开始粉刷,请你尽快告诉他答案。

输入

第一行一个正整数T,表示测试数据组数

对于每一组测试数据数据:

第1行:一个正整数K

第2行:K个正整数,表示第i桶油漆可以粉刷的石柱个数,Ci。

输出

对于每组输入数据,输出一行一个整数,表示粉刷的方案数mod 1000000007。

样例输入

3
3
1 2 3
5
2 2 2 2 2
10
1 1 2 2 3 3 4 4 5 5

样例输出

10
39480
85937576

数据范围

30% N≤10, T≤5

50% N≤15, T≤5

80% K≤15,Ci≤5,T≤500

100% K≤15,Ci≤6,T≤2000

分析

显然的组合数学题。。。(我考场上打炸了。。。)

我们考虑定义状态 f [ i ] [ j ] f[i][j] f[i][j]为当前刷到第 i i i根石柱,所用颜色为 j j j的方案数。显然这是有后效性的(没错这就是我的思路。。。)

考虑改变状态的定义。由于我们可以将同颜色的石柱看做相同的,所以我们可以一次性的插入 c i c_i ci​根石柱并和其他石柱讨论以计算方案数。

我们定义状态 f [ i ] [ j ] f[i][j] f[i][j]为将前 i i i种颜色全部涂完并产生了 j j j对相邻的石柱颜色是相同的方案数。设 s = ∑ k = 1 i c k s=\sum_{k=1}^{i}{c_k} s=∑k=1i​ck​。

首先我们将这些柱子分为 k k k组(每组至少一个),这是个显然的隔板法,答案为 C c i − 1 i − 1 C_{c_i-1}^{i-1} Cci​−1i−1​。

插入时势必将某些已经成对的柱子分开,我们设将已经成对的柱子分开的个数为 t t t,则将这 k k k组柱子插入成对柱子中的方案数为 C k t C_{k}^{t} Ckt​。

剩下的柱子就可以随便放了,方案数为 C s − j + 1 k − t C_{s-j+1}^{k-t} Cs−j+1k−t​。

这样在新状态下所产生的相邻的石柱颜色相同的数量为 j + c i − k − t j+c_i-k-t j+ci​−k−t

所以我们得出状态转移方程式: f [ i ] [ j + c i − k − t ] = ∑ f [ i − 1 ] [ j ] × C c i − 1 k − 1 × C k t × C s − j + 1 k − t f[i][j+c_i-k-t]=\sum{f[i-1][j]\times C_{c_i-1}^{k-1}\times C_{k}^{t}\times C_{s-j+1}^{k-t}} f[i][j+ci​−k−t]=∑f[i−1][j]×Cci​−1k−1​×Ckt​×Cs−j+1k−t​

答案即为 f [ K ] [ 0 ] f[K][0] f[K][0]。

还有一种用七维DP的方法,这里简要提一下。

定义状态 f [ i ] [ j ] [ k ] [ l ] [ o ] [ p ] [ q ] f[i][j][k][l][o][p][q] f[i][j][k][l][o][p][q]表示当某些颜料剩余数量为 1 1 1的数量为 i i i,为 2 2 2的数量为 j j j…上一次是将数量为 q q q的颜料变到 q − 1 q-1 q−1的方案数。

那么转移贼暴力。。。这里就不提及了。注意当重复选择 q q q的时候要减一。

答案。。。

这个方法容易爆空间,我们要压掉最后一维,方法就不提了。

参考代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;typedef long long ll;
const int Maxn=100;
const int Maxk=15;
const int Maxc=6;
const ll Mod=1e9+7;int K,Col[Maxk+5];ll fac[Maxn+5],inv[Maxn+5];
ll QuickPow(ll a,ll k) {ll ret=1;while(k) {if(k&1)ret=(ret*a)%Mod;a=(a*a)%Mod;k>>=1;}return ret;
}
void Init() {fac[0]=1;for(int i=1;i<=Maxn;i++)fac[i]=fac[i-1]*i%Mod;inv[Maxn]=QuickPow(fac[Maxn],Mod-2),inv[0]=1;for(int i=Maxn-1;i>=1;i--)inv[i]=inv[i+1]*(i+1)%Mod;
}
ll C(int n,int m) {if(m>n)return 0;return fac[n]*inv[m]%Mod*inv[n-m]%Mod;
}ll f[Maxk+5][Maxn+5];int main() {#ifdef LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifInit();int _;scanf("%d",&_);while(_--) {scanf("%d",&K);for(int i=1;i<=K;i++)scanf("%d",&Col[i]);memset(f,0,sizeof f);f[0][0]=1;int sum=0;for(int i=1;i<=K;i++) {for(int j=0;j<=sum;j++) {if(f[i-1][j]==0)continue;for(int k=1;k<=Col[i];k++)for(int t=0;t<=j&&t<=k;t++)f[i][j+Col[i]-k-t]=(f[i][j+Col[i]-k-t]+f[i-1][j]*C(Col[i]-1,k-1)%Mod*C(sum-j+1,k-t)%Mod*C(j,t)%Mod)%Mod;}sum+=Col[i];}printf("%lld\n",f[K][0]);}return 0;
}

中山纪中训练游记Day1+8.1模拟赛题解相关推荐

  1. 中山纪中集训游记Day2+8.2模拟赛题解

    Part.I游记 纪中的OJ真的...今天下午又炸一次... 今天模拟赛竟然是考的集训队互测的题...做到自闭... 一开考看见第一题,给我的感觉是要写树套树...然而我不想写... 然后就去看了第二 ...

  2. 2019纪中暑假游记+总结

    Travels总篇\texttt{Travels总篇}Travels总篇 7/4\texttt{7/4}7/4 下午才去纪中,早上就一大早和同学出去玩,看了蜘蛛侠然后到3点多才出发. 因为走南沙大桥所 ...

  3. 2018纪中集训游记

    DAY  0 从家出发的时候,阴天了,开始祈祷不要下雨(之后貌似起飞的时候下了大雨,不过当时在云层里只感觉到了一丢丢颠簸?) 飞机给咕咕了半个小时,期间一直在被老头子呵斥不要奶飞机,我一直在叨叨:飞机 ...

  4. 2021.7纪中快乐游记(下)

    DayDayDay 7:7:7: 7.187.187.18 周日放假! 早上居然6:30就起来了.去吃了个早餐就回机房. 按照原计划,应该是要写作业的,所以很自觉的拿出数学试卷写完一张半. 然后看到c ...

  5. [2019.7.31~2019.8.15]纪中集训游记

    开坑 这是一篇(也许会变成一套)无聊的游记. https://jzoj.net/senior/ Day0(2019.7.31) 启程 如果没记错的话,与同学们相约在机场的时间应该是9:00,然而我10 ...

  6. 【纪中受难记】——Day1:没有爆零

    上午考完感觉心情一般般,第二题貌似可以打表但是没打,自认为是"简单的模拟题",其他题没动. 下午出来:0/36.4/0,十分心痛. 果然,菜就是原罪. 1.游戏 Descripti ...

  7. 中山纪中集训Day2又是测试(划水)

    A组T1 bzoj 2674 Attack Description chnlich 非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜.现在,他要开始征服世界的旅途了.他的敌人有N 座城市和N 个太守 ...

  8. 中山纪中集训Day2又是测试

    A组T1 bzoj 2674 Attack Description chnlich 非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜.现在,他要开始征服世界的旅途了.他的敌人有N 座城市和N 个太守 ...

  9. 纪中训练5月23日提高组T1

    [USACO 2017 US Open Silver]Bovine Genomics 题解: 暴力 把ACGT对应成数字,然后记录 接着就是暴力找三个位置 然后又是暴力判断 综上所述: 暴力 #inc ...

最新文章

  1. torch.nn.Embedding
  2. leetcode二维查找
  3. python流程控制语句-python 流程控制语句
  4. 学习Docker从小白到入门
  5. HarmonyOS之组件通用的XML属性总览
  6. 一程序员被判 9 个月:因薪酬等问题离职,rm -f * 删库,瘫痪 6 个小时
  7. yii学习笔记--url解析
  8. 注解形式控制器配置(3)
  9. spring boot 教程(二)模板依赖
  10. Handler机制的理解与使用
  11. 如何正确预防网页中的5种“隐形杀手”
  12. 心电图分析软件_家用心电图机,一键出报告,让你在家就能看懂心电图!
  13. 机器学习实战2之科比篮球生涯得分数据分析
  14. python mro文件_python MRO问题
  15. SEO搜索引擎优化步骤建议
  16. LINUX IIO子系统分析之五IIO BUFFER子模块实现分析
  17. Nginx + Lua 搭建网站WAF防火墙
  18. 选计算机硬盘原则和注意事项,旧电脑升级是升内存还是SSD?按照这个原则就对了!...
  19. 【LeetCode】279. 完全平方数 【动态规划】【四平方和定理】
  20. Python从网易云音乐、QQ 音乐、酷狗音乐、虾米音乐等搜索和下载歌曲

热门文章

  1. 固生堂完成3770万美元E-1轮融资,投后估值5.03亿美元
  2. Axure RP8概要页面不见了
  3. 子序列和子串问题算法的全面总结
  4. 北京博奥智源,会计素养与智能工具应用平台开发功能详解
  5. 邮箱的格式怎么写,安全邮箱的格式是什么样的?
  6. 恢复磁盘I:时出错,在此驱动器上找不到恢复密钥。无法解锁此驱动器。
  7. 【论文写作-2】Word中如何创建目录
  8. 网易数帆对 CIlium 容器网络的探索和实践
  9. 为什么越来越多的人喜欢一个人独来独往
  10. SQLyog的快捷键大全