您的位置:首页 > 大数据 > 人工智能

2012 Multi-University Training Contest 3

2012-07-31 18:43 288 查看
1001 HDU4320 Arcane Numbers 1

GCD 0MS 无压力

代码:

View Code 1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 using namespace std;
5 #define lson l,m,rt<<1
6 #define rson m+1,r,rt<<1|1
7 #define LL __int64
8 const int N=100002;
9 LL add[N<<2];
LL sum[N<<2];
void pushup(LL rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(LL rt,LL m)
{
if(add[rt])
{
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*(m-(m>>1));
sum[rt<<1|1]+=add[rt]*(m>>1);
add[rt]=0;
}
}
void build(LL l,LL r,LL rt)
{
add[rt]=0;
if(l==r)
{
sum[rt]=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(LL L,LL R,LL c,LL l,LL r,LL rt)
{
if(L<=l&&r<=R)
{
add[rt]+=c;
sum[rt]+=(LL)c*(r-l+1);
return ;
}
pushdown(rt,r-l+1);
LL m=(l+r)>>1;
if(L<=m)
update(L,R,c,lson);
if(m<R)
update(L,R,c,rson);
pushup(rt);
}
LL query(LL L,LL R,LL l,LL r,LL rt)
{
if(L<=l&&r<=R)
{
return sum[rt];
}
pushdown(rt,r-l+1);
LL m=(l+r)>>1;
LL ret=0;
if(L<=m)
ret+=query(L,R,lson);
if(m<R)
ret+=query(L,R,rson);
return ret;
}
int main()
{
int t,k=0;
scanf("%d",&t);
while(t--)
{
k++;
int i,j;
__int64 a,b,c,d;
scanf("%I64d%I64d",&a,&b);
build(1,N,1);
for(i=0;i<a;i++)
{
scanf("%I64d%I64d",&c,&d);
update(c,d,1,1,N,1);
}
printf("Case #%d:\n",k);
for(j=0;j<b;j++)
{
scanf("%I64d",&c);
printf("%I64d\n",query(c,c,1,N,1));
}
}
return 0;
}

附:

官方题解:

1001检查A中的质因子 是否都在 B中被包含。

1002按位统计计算,如果枚举 那么复杂度就是 64 * N第一条当统计第K位的时候 可以注意到 第 B+T*A 和 B+(T+2^(K+1))*A 位是相同的那么 第K位的时候 只需要统计2^K 次就可以了 第二条当统计第K位的时候 可以注意到 连续的 (2^K)/A都是连续的0 或者连续的1 所以可以考虑直接连续记录(2^K)/A个结果。 那么 第K位的时候 只需要统计N / ((2^K)/A)次就可以了 综合 第一条 第二条 那么 第K位的时候 只需要统计 2^K/((2^K)/A) 复杂度 变为O(A) 总复杂度为64*A 1003【题目大意】

有N颗糖果和M个小孩,老师现在要把这N颗糖分给这M个小孩。每个小孩i对每颗糖j都有一个偏爱度Aij,如果他喜欢这颗糖,Aij = k,否则Aij = 1。小孩i觉得高兴当且仅当ΣCij×Aij >= Bi,j=1,2,…,N,若他分得了糖j,Cij = 1,否则Cij = 0。问能否合理分配这N颗糖,使得每个小孩都觉得高兴。【建模方法】(最大费用最大流) 本题有一个突破点就是:他喜欢这颗糖,Aij = k,否则Aij = 1,关键在于如果他不喜欢这个糖分给他一样可以获得1点的欢乐值。也就是说如果之前分配了的糖给了小孩一定的欢乐值,不够bi,可以直接用随意的糖去填满。 首先我们要求欢喜值>=bi,是否可以认为当我获得欢喜值为bi后,多余欢喜值对这个结果的满足是没有贡献的。也就是说,你可以用一个容量来控制分配糖对小孩欢喜值的控制,让获得欢喜值最多为bi。如果不够,最后用一些1的糖来填满。 而这个容量就是bi/c,获取贡献为k,bi%c(>1)的也是可以用一个能让这个小孩欢喜的糖来贡献,但是其费用只为bi%c。 对于小孩来说,最大费用最大流后,糖分配的贡献值为最大费用,剩余糖就是(n-最大流),然后用这些糖去填不满的,只要满足总和大于Σbj。就可以分配了。具体建模方案1:(s,i,1,0);(i,j,1,0);(j,t,bj/k,k);If(bj%k>1)(j,t,1,bj%k)Ans = 费用 + N – 最大流 >= Σbj 则满足要求具体建模方案2:(s,I,1,0) (I,j,1,0)(j,t,bj/k,k-1);If(bj%k>1)(j,t,1,bj%k-1);Ans = 费用+N >= Σbj 则满足要求当k = 2时候,可以不用费用流,最大流即可。

一种最直观的想法就是每颗糖i作为一个点并连边(s, i, ?),每个小孩j作为一个点并连边(j, t, Bj)。若小孩j喜欢糖果i则连边(i, j, 2),否则连边(i, j, 1),然后求一次最大流看是否等于ΣBj。但是问题也很明显,我们还没有给与源点关联的边确定容量。实际上我们无法确定它们的容量,因为最大流无法实现这样一种控制:一个点有若干条出边,容量不尽相同,现在要求经过该点的流可以任选一条出边流走,且一旦选定之后就只能从这条边流而不能再进入其他的出边。因此我们无法确定与源关联的边的容量,因为经过每颗糖i的流无法在出边容量有1又有2的情况下作出正确的选择。 那么是否就没有办法了呢?虽然流无法在容量有1又有2的情况下作出正确的选择,但却可以在容量有1又有0的情况下最自然地作出正确的选择,流过去就表示选择了那条出边,且因为容量为1,不会再有流进入其他的出边。那么此题的构图方法也就出来了:每颗糖i作为一个点并连边(s, i, 1),每个小孩j作为一个点并连边(j, t, floor(Bj/2)),若小孩j喜欢糖果i则连边(i, j, 1),否则连边(i, j, 0)或者干脆不连边,效果一样。设最大流为ans,若ans+N >= ΣBj则可以满足要求。为什么?因为每颗糖迟早都要分给某个小孩,它一定会为总权值贡献1,只不过如果它分给了喜欢它的小孩就再额外贡献1。现在我只考虑这额外的1单位贡献究竟能送出去多少,最后加上基值N并与ΣBj比较即可。 1004

这道题求两个字符串编辑距离的部分用动态规划就可以了,如果不加任何优化,总的复杂度是1500*1000*10*10,时间给了1s,如果写的效率比较高,有可能可以水过。标程的用到了一个叫做BK-Tree的数据结构优化一下,其实原理很简单,可以参考wiki http://en.wikipedia.org/wiki/BK-tree和matrix67的blog http://www.matrix67.com/blog/archives/333 1005题目描述:2000个点的有向图,保证任意两点间仅有一条有向边。解题报告: 增量算法,充分利用“任意两点间仅有一条有向边”的性质。 假设前面已经加入了N个点,现在来了第N+1个点。 那么一定能将N个点分成left和right两部分,使得N+1号点到left有边,right到N+1号点右边(因为任意两点间都有边),那么,如果left的任意一个点l到right任意一个点r有边的话,那么就有答案N+1->l->r->N+1这样一个长度为3的环。 那么每次加入N+1号点后,用O(N)的复杂度求出左边的数量leftnum,右边的数量rightnum,left的出度和leftout,left的入度和leftin。 如果left没有一条到right的边,则一定满足: leftin = leftout + leftnum * rightnum(left和right任意两点右边,如果没有左到右的,那么leftnum*rightnum条边都是右到左的) 那么,如果leftin != leftout + leftnum * rightnum,则暴力枚举左点,右点即可得到答案。 总体复杂度O(n^2) 附加一份其他人的解题报告lengxiang解题报告: 我稍微的看了下出题人的解题报告,没咋看懂。稍微有所启发。写了一个不一样的代码,数据同样通过。 归结为1个条件,任何两人都有边,要么出要么入。 对于有向三元环,我们知道找到:A->B->C->A ,B->C->A->B ,C->A->B->C 是一样的,这给0(n^2)的算法提供了基础。 对于每次枚举i,我们在(0~i-1)的范围看下有多少个i指向的点(剩下的就是指向i的点),同时算下i指向的点的出度和。就可以知道这些 i指向的点 指向 指向i的点(剩下的点)的数目,如果 num * (num - 1) / 2 < sumout 那么就是被指向的点有指出去了,这样就形成了3元环。 否则,剩下的就是更新下出度即可,继续执行下一个节点。 1006这个题就是比较裸的区间更新,单点查询的线段树。一开始需要把要查询的点和花开的时间和花谢的时间一起离散化了,这样查询的时候就方便多了。 1007

本题题意很简单,给出n个人每次4人进行比赛其他人等待,胜者继续,负者排到最后,连续或得m次胜利的人成为最终的赢家,求第k个人最终获得胜利的概率是多少? 对于这题,我们首先确立一个这样的模型: x1先赢了i局,正在于x2,x3,x4赌斗,后面依次有x5,x6,……,xn等待。用P[i][j]表示x1先赢了i局的情况下,当前的xj获胜的概率。不难得到以下的一些式子:

i < m

P[i][j] = P[i + 1][j] * 1/4 + P[1][n - 2] * 3/4 j = 1P[i + 1][n - 2] * 1/4 + P[1][1] * 1/4 + P[1][n - 1] * 2/4 j = 2P[i + 1][n - 1] * 1/4 + P[1][1] * 1/4 + P[1][n - 1] * 1/4 + P[1]
* 1/4 j = 3P[i + 1]
* 1/4 + P[1][1] * 1/4 + P[1]
* 2/4 j = 4P[i + 1][j - 3] * 1/4 + P[1][j - 3] * 3/4 j>=4 i = m

P[i][j] = 1 j = 10 j != 1 于是我们得到了一个未知数为n*m个的方程组。用高斯消元法解之即可。

值得注意的是,以上思想并不难想到,但是普通的高斯消元法会由于舍入误差使得结果出现很大的偏差,这里我们采用的是分数形式的高斯消元的解法。

1008

首先利用旋转卡壳计算出每个点的凸包,由于密度公式非常特殊,则利用公式微积分即可算得每个点落到上面的概率。具体详见代码 1009本题主要考察DP状态转移以及数据结构的使用。相邻块不能相同的最长周长的正方形,直接用O(1)转移的二维dp可以实现,g[i][j]表示右下角选为(i,j)的周长最长正方形,根据图像特性,g[i][j] = min( g[i-1][j] , g[i][j-1] ) or g[i][j] = min( g[i-1][j] , g[i][j-1] ) + 1,是否需要加1取决于对于块的颜色与map(i,j)上的颜色是否相同。对于周长最长的同色矩形,首先O(n)枚举矩形的下底,然后从左至右O(m)依次枚举相应左右边界的最大值,枚举工作使用队列提速,询问过程涉及到区间更新区间查询的功能,使用线段树优化查询效率,复杂度O(n * m * lg(n)); 从左至右O(m)枚举时,也可以使用栈来保存每一列连续颜色的高度,同时可以求周长的最大值,复杂度(n * m)。 1010

本题是一道简单的模拟题,关键点是看懂题目绕口的定义,然后按照题目所给的公式求解即可。实现过程可以使用map来判断检索出的url是否为相关文件,使用istringstream处理字符串操作。具体如何实现都行,总之本题考察读题和基本字符串处理。 1011

搜索+剪枝 如果遇到已经100%的情况就直接break 一开始可以不去考虑不会补充新的棋子的情况 如果有100%的情况 那也可以直接break了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: