中山纪中集训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)然后 ...
随机推荐
- 快速精通Mac效率神器Alfred以及常用workflow
概述 Alfred基础在上一篇 大纲 名称 作用 类别 出处 修改日期 Github 更便捷地使用Github 开发编程 Github 2017-01-28 Github Search Github搜 ...
- 前端以及django零碎补充
前端 1. js的循环each 前端需要循环,可以借助each这个方法 var dic = {'key1':'value1','key2':'value2'}; ']; //each(变量, 方法) ...
- DDL 操作数据库
DDL 操作数据库:常用的操作 CRUD 一.C(create)创建 1.创建数据库 create database 数据库名称; 2.创建数据库,判断是否存在,再创建(如果存在,就不再创建) cre ...
- WampServer详解
php能做什么,它是运行在服务器端的,web网站大部分数据都是存储在服务器上的,PHP就是用来处理这些存储在服务器的数据.跨平台,服务器可以是多种平台上的服务器,脚本语言,免费. wampserver ...
- 【转】高性能网络编程3----TCP消息的接收
这篇文章将试图说明应用程序如何接收网络上发送过来的TCP消息流,由于篇幅所限,暂时忽略ACK报文的回复和接收窗口的滑动. 为了快速掌握本文所要表达的思想,我们可以带着以下问题阅读: 1.应用程序调用r ...
- 交互式计算引擎MOLAP篇
交互式计算引擎MOLAP篇 摘自:<大数据技术体系详解:原理.架构与实践> MOLAP是一种通过预计算cube方式加速查询的OLAP引擎,它的核心思想是“空间换时间”,典型代表包括Drui ...
- 基于yum的方式安装Cloudera Manager Server(使用Mysql 8.0版本)
基于yum的方式安装Cloudera Manager Server(使用Mysql 8.0版本) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装和配置元数据库 1>. ...
- jqGrid行编辑配置,方法,事件
行编辑可以在行修改后更新数据,如下图所示 用户用鼠标点击选择一行,jqGrid将可编辑的字段转换为数据输入单元,如上面图所示.不可编辑的列,如id,不会转为可输入单元,而是保持不变.可以通过配置col ...
- 用java刷剑指offer(二叉树中和为某一值的路径)
题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大 ...
- lvm快照备份mysql
快照备份原理(从其他博客看的): 原理:通过lvm快照给lvm真身拍个照片,当lvm真身发送改变时,lvm快照把lvm真身改变之前的内容存放在快照上,这样在lvm快照有效的这段时间内,我们看到的lvm ...