中山纪中集训Day1测试(摸鱼)
AT3 粉刷匠
Description
赫克托是一个魁梧的粉刷匠,而且非常喜欢思考= =
现在,神庙里有N根排列成一直线的石柱,从1到N标号,长老要求用油漆将这些石柱重新粉刷一遍。赫克托有K桶颜色各不相同的油漆,第i桶油漆恰好可以粉刷Ci根石柱,并且,C1+C2+C3…CK=N(即粉刷N根石柱正好用完所有的油漆)。长老为了刁难赫克托,要求相邻的石柱颜色不能相同。
喜欢思考的赫克托不仅没有立刻开始粉刷,反而开始琢磨一些奇怪的问题,比如,一共有多少种粉刷的方案?
为了让赫克托尽快开始粉刷,请你尽快告诉他答案。
Input
第一行一个正整数T,表示测试数据组数
对于每一组测试数据数据:
第1行:一个正整数K
第2行:K个正整数,表示第i桶油漆可以粉刷的石柱个数,Ci。
Output
对于每组输入数据,输出一行一个整数,表示粉刷的方案数mod 1000000007。
Sample Input
3
3
1 2 3
5
2 2 2 2 2
10
1 1 2 2 3 3 4 4 5 5
Sample Output
10
39480
85937576
Data Constraint
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]表示前i种颜色的石柱全部拿来排列后,有j根石柱它们的颜色与它们左边的那个石柱相同。
填表法不是很好做,所以我们直接考虑刷表法。
对于每一个状态f[i][j],因为每种颜色的个数是已知的,所以当前石柱所组成的序列的长度是已知的,设为sum。
设第i种颜色石柱的数量是a[i],那么从f[i]转移到f[i+1],将有a[i+1]个石柱将插入到序列里面。
显然,插入时会使原来在一起的两块石柱分开的这种插入会影响到状态本身,所以应该将它单独讨论。
设插入时会插入到p个两边颜色相同的空,q个其他情况的空,那么p+q<=sum+1且p+q<=a[i+1],还剩下a[i+1]-p-q个石柱的插入,它们必然会产生新的颜色相同且相邻的石柱。
那么f[i][j]就可以转移到f[i+1][j-p+a[i+1]-p-q],p与q都可以枚举。将a[i+1]个球放入p+q个空中且不能不放,根据隔板法可知要乘上C(a[i+1]-1,p+q-1).又要在j个两边颜色相同的空中选p个则又要乘上C(j,p),还要在剩下sum+1-j个空中选q个,就还要乘上C(sum+1-j,q)。
直接贴代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#define mod 1000000007
using namespace std;
int C[][],f[][],T,n,a,sum;
int main()
{
C[][]=;
for(int i=;i<=;i++)
{
C[i][]=;
for(int j=;j<=i;j++)
C[i][j]=(C[i-][j]+C[i-][j-])%mod;
}
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);sum=;f[][]=;
for(int i=;i<=n;i++)
{
scanf("%d",&a);
for(int j=;j<=sum+a+;j++)f[i][j]=;
for(int j=;j<=sum;j++)
{
for(int p=;p<=min(j,a);p++)
{
for(int q=;q<=min(sum+-j,a-p);q++)
{
if(!q&&!p)continue;
long long ans=f[i-][j];int nex=j-p+a-p-q;
(ans*=1ll*C[a-][p+q-])%=mod;
(ans*=1ll*C[j][p])%=mod;
(ans*=1ll*C[sum+-j][q])%=mod;
(f[i][nex]+=ans)%=mod;
}
}
}
sum+=a;
}
printf("%d\n",f[n][]);
}
}
AT2 Vani和Cl2捉迷藏
Description
vani和cl2在一片树林里捉迷藏……
这片树林里有N座房子,M条有向道路,组成了一张有向无环图。
树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。如果从房子A沿着路走下去能够到达B,那么在A和B里的人是能够相互望见的。
现在cl2要在这N座房子里选择K座作为藏身点,同时vani也专挑cl2作为藏身点的房子进去寻找,为了避免被vani看见,cl2要求这K个藏身点的任意两个之间都没有路径相连。
为了让vani更难找到自己,cl2想知道最多能选出多少个藏身点?
Input
第一行两个整数N,M。
接下来M行每行两个整数x、y,表示一条从x到y的有向道路。
Output
一个整数K,表示最多能选取的藏身点个数。
Sample Input
4 4
1 2
3 2
3 4
4 2
Sample Output
2
Data Constraint
对于20% 的数据,N≤10,M<=20。
对于60% 的数据, N≤100,M<=1000。
对于100% 的数据,N≤200,M<=30000,1<=x,y<=N。
虽然不是很懂但还是应该有的分析
选择一个藏身点后就会有一些路径被废掉不能再选。
然后听说这是求DAG的最小不相交路径覆盖?将原图的点拆成x部与y部,若a能到达b则连Xa指向Yb。
然后DAG的最小路径覆盖=原图的结点数-对应二分图的最大匹配数。(????)
个人理解(乱理解):每一条边代表了原图中的一条路径,每一个匹配代表匹配边两边的点被连在一起,即这条路径上有一个点被选择,整条路径将不再可用。因为求的是最大匹配,所以没有匹配的点在原图中就是一条路径的终点,这些点都可作为藏身点,故答案为原图的结点数-对应二分图的最大匹配数。
代码:
#include<cstdio>
#include<cstring>
int n,m,ans,mat[],vis[],V[][];
int solve(int x)
{
for(int i=;i<=n;i++)
{
if(V[x][i]&&!vis[i])
{
vis[i]=;
if(!mat[i]||solve(mat[i]))
{
mat[i]=x;
return ;
}
}
}
return ;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,u,v;i<=m;i++)scanf("%d%d",&u,&v),V[u][v]=;
for(int k=;k<=n;k++)for(int i=;i<=n;i++)for(int j=;j<=n;j++)
if(i!=j)V[i][j]=V[i][j]||(V[i][k]&&V[k][j]);
for(int i=;i<=n;i++)
{
memset(vis,,sizeof vis);
ans+=solve(i);
}
printf("%d\n",n-ans);
}
AT1 水叮当的舞步
Description
水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。
为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~
地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。
水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,地毯左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。
由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。
Input
每个测试点包含多组数据。
每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。
接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。
N=0代表输入的结束。
Output
对于每组数据,输出一个整数,表示最少步数。
Sample Input
2
0 0
0 0
3
0 1 2
1 1 2
2 2 1
0
Sample Output
0
3
Data Constraint
对于30%的数据,N<=5
对于50%的数据,N<=6
对于70%的数据,N<=7
对于100%的数据,N<=8,每个测试点不多于20组数据。
分析
没看完虹猫蓝兔的我肯定不会做这个题。
观察数据范围,n最大也就8,直接暴力出奇迹,剪枝后复杂度玄学。
先从小到大枚举最大搜索深度(听说这叫迭代加深?),注意不能二分,因为这是指数级别的复杂度增长。
然后进行两个剪枝,一个是变色前统计一下左上角联通块附近有哪几种颜色,变的时候就只用变成这些颜色。
另一个是当 当前深度 加上 剩下联通块的颜色的种类数 大于我们枚举的最大搜索深度时可以直接return 0(听说这跟A*有关?);
写的时候注意局部变量与全局变量,不能混在一起。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,tmp,I,color[],ma[][],vis[][],vised[][],used[];
int cnt1(){int ans=;for(int i=;i<=;i++)ans+=(color[i]>);return ans;}
void cnt2(int x,int y)
{
if(ma[x][y]==-||vised[x][y])return;
if(ma[x][y]){used[ma[x][y]]=;return;}vised[x][y]=;
cnt2(x+,y);cnt2(x-,y);cnt2(x,y+);cnt2(x,y-);
}
void print(int x,int y,int c,int dep)
{
if(ma[x][y]==-||(ma[x][y]!=c&&ma[x][y]!=)||vised[x][y])return;vised[x][y]=;
if(ma[x][y]==c)ma[x][y]=,color[c]--,vis[x][y]=dep;
print(x+,y,c,dep);print(x-,y,c,dep);print(x,y+,c,dep);print(x,y-,c,dep);
}
bool solve(int noww,int t)
{
if(noww+cnt1()->t)return ;//这个地方的1减去会多搜索,不减不严谨
if(==(color[]>)+(color[]>)+(color[]>)+(color[]>)+(color[]>)+(color[]>))return ;
memset(vised,,sizeof vised);memset(used,,sizeof used);
I=noww;cnt2(,);int u[]={};memcpy(u,used,sizeof u);
for(int i=;i<=;i++)
{
if(!u[i])continue;
memset(vised,,sizeof vised);
print(,,i,noww);
if(solve(noww+,t))return ;
for(int i1=;i1<=n;i1++)for(int j=;j<=n;j++){if(vis[i1][j]==noww)color[ma[i1][j]=i]++,vis[i1][j]=-;}
}
return ;
}
int main()
{
memset(ma,-,sizeof ma);
while(scanf("%d",&n)&&n)
{
memset(color,,sizeof color);
memset(vis,-,sizeof vis);
memset(ma,-,sizeof ma);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&ma[i][j]),color[++ma[i][j]]++;
for(int i=;i<=n*n;i++)
if(solve(,i)){printf("%d\n",i);break;} }
}
中山纪中集训Day1测试(摸鱼)的更多相关文章
- 「中山纪中集训省选组D1T1」最大收益 贪心
题目描述 给出\(N\)件单位时间任务,对于第\(i\)件任务,如果要完成该任务,需要占用\([S_i, T_i]\)间的某个时刻,且完成后会有\(V_i\)的收益.求最大收益. 澄清:一个时刻只能做 ...
- 纪中集训 Day1
今天早上起来吃饭,发现纪中伙食真的是太差了!!!什么都不热,早餐的面包还好,然后就迎来了美好的早晨= = 早上做一套题,T1T2果断秒,T3一看就是noi原题,还好看过题解会写,然后就愉快的码+Deb ...
- 中山纪中集训Day5叒是测试(划淼)
A组T1 矩阵游戏(game) 九校联考24OI__D1T1 问题描述 LZK发明一个矩阵游戏,大家一起来玩玩吧,有一个N行M列的矩阵.第一行的数字是1,2,…M,第二行的数字是M+1,M+2…2*M ...
- 中山纪中集训Day4双是测试(划沝) 九校联考-DL24凉心模拟Day2
A组T1 锻造 (forging) 1.1 题目背景 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现......自己连一个史莱姆 ...
- 中山纪中集训Day2又是测试(划水)
A组T1 bzoj 2674 Attack Description chnlich 非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜.现在,他要开始征服世界的旅途了.他的敌人有N 座城市和N 个太守 ...
- 「中山纪中集训省选组D4T1」折射伤害 高斯消元
题目描述 在一个游戏中有n个英雄,初始时每个英雄受到数值为ai的伤害,每个英雄都有一个技能"折射",即减少自己受到的伤害,并将这部分伤害分摊给其他人.对于每个折射关系,我们用数对\ ...
- 「中山纪中集训省选组D2T1」书堆 欧拉常数
题目描述 蚂蚁是勤劳的动物,他们喜欢挑战极限.现在他们迎来了一个难题!蚂蚁居住在图书馆里,图书馆里有大量的书籍.书是形状大小质量都一样的矩形.蚂蚁要把这些书摆在水平桌子的边缘.蚂蚁喜欢整洁的布置,所以 ...
- 纪中集训 Day 2
今天(其实是昨天= =)早上起来发现好冷好冷啊= = 吃完饭就准备比赛了,好吧B组难度的题总有一道不知到怎么写QAQ 太弱了啊!!! 蒟蒻没人权啊QAQ 今天第4题不会写,在这里说说吧 题目的意思就是 ...
- 纪中集训 Day 0?
好吧昨天的等到今天才来写,现在超不想刷题,来写下blog吧= = 坐了近10H的火车终于来到了中山市 火车上在看空之境界,等有时间补下动画吧= = 到了宿舍各种不习惯(现在才发现还是母校好QAQ)然后 ...
随机推荐
- flutter 动画
AnimatedCrossFade AnimatedCrossFade让俩个子widget 交替淡入淡出. class AnimatedCrossFade1 extends StatefulWidge ...
- 制作IOS ANE的基本流程
来源:http://www.swfdiy.com/?p=1239 1. 使用xcode新建ios上的static library 工程 2. 从air sdk/include里拷贝flashrunti ...
- SAP开源的持续集成-持续交付的解决方案
SAP开源的持续集成/持续交付的解决方案: (1) 一个叫做piper的github项目,包含一个针对Jenkins的共享库和一个方便大家快速搭建CI/CD环境的Docker镜像: (2) 一套SAP ...
- GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?
一.GC如何判断一个对象为”垃圾”的java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”.那么GC具体通过什么手段来 ...
- CPNtools 模拟工具适合分析什么样的协议
最近梳理和CPNtools和Scyther之间的性能和差别.方便后面整理使用 1.库所的托肯值是什么? 托肯值也叫作令牌, 即网络系统中的资源,托肯的数目值代表了网络赋予的资源大小.在一个活的网络系统 ...
- Altium designer 如何将2D PCB转换成3D
点击键盘数字键的3,即可,2键可以切换回2D效果,但是如果要看元器件的3D效果,那么元器件封装必须带有3D模型才行! 先按3切换到三维界面,然后按住shift不放,按鼠标右键调整视图角度.
- 渗透之路基础 -- XXE注入漏洞
XXE漏洞 XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件, ...
- 利用Minhash和LSH寻找相似的集合
from: https://www.cnblogs.com/bourneli/archive/2013/04/04/2999767.html 问题背景 给出N个集合,找到相似的集合对,如何实现呢?直观 ...
- markdown里面编辑代码
转:http://c.biancheng.net/view/6623.html ------------------------------------------------------------ ...
- mysql占用内存过高调优方法
最近测试一个站点,用mysql 5.6+mencache 内存16GB,但是进行查询的时候还是导致CPU占用过高,达到80%左右,所以想办法如何进行调优.以下几个参数进行参考选择 优化mysql数据 ...