【AC_LCC_CWJ第五场】ZOJ Monthly, January 2011(ZOJ3457~ZOJ3466)

……这场比较久了,只记得当时被屠了。

【ZOJ3457】

模拟题,主要是模拟1/x的这个除法。细节比较多,比较繁琐……

最后打表搞之。

【ZOJ3458】

题目大意:计算floor((sqrt(a)+sqrt(b))^n) % 2(a+b)    保证 0 < b-a < 1+2sqrt(a) 且 n%2==0

算法分析:

师父当时告诉偶们一个结论 (sqrt(a)+sqrt(b))^(2n) + (sqrt(a)-sqrt(b))^(2n)是整数。

把^(2n)里的2放进去,变成     (题目保证了n%2==0,所以可以这样变形……)

令A=       B=

然后求该数列的母函数:1 , A^1+B^1 , A^2+B^2 , A^3+B^3 ……   ————————令这个数列第i项为Z[i]

G(x)=1 + (A^1+B^1)x + (A^2 + B^2)x^2 + (A^3+B^3)x^3  ……

G(x)=

然后把两个分母乘起来(1-Ax)(1-Bx)得到1 -(A+B)x +ABx^2

∴Z[n] – (A+B)Z[n-1] + (A*B)Z[n-2]=0

然后A+B=2*(a+b),A*B=(a-b)^2

移项即得到递推式。然后用矩阵乘法可以很轻易得到Z[n]。

回归到原题,0 < b-a < 1+2sqrt(a),那么容易得到0

然后题目求floor((sqrt(a)+sqrt(b))^n) % 2(a+b) ,那么就等于求(Z[n/2]-1) % 2(a+b)

里面因为是% 2(a+b),所以有点特殊性,最后的式子可以化简,不过矩阵暴力之也差不多……

【ZOJ3459】

题目大意:台上有4张牌,司马和张角都有一定数量的手牌(每个人的手牌数量∈[1,6]),司马先手,然后每个人轮流换台上的牌。如果某个人在这个回合选择不换牌,那么游戏结束,这时候如果台面上的4张牌可以组成算出24点,那么司马赢,否则张角赢。特别地,司马在第一回合即使不换牌,游戏也不会结束。

算法分析

先暴力求24点的所有可能。然后博弈树搜索之,基本上就是极大极小过程。

【ZOJ3460】

题目大意:在二维平面上m个导弹发射塔,和n个目标,发射塔发射一枚导弹需要T1这么多时间,然后发射完以后,发射塔就可以准备下一次发射,这个准备时间为T2,导弹发射以后会以速度V直线飞到目标处。问最少要多少时间将所有的目标摧毁。

算法分析

二分答案,然后将发射塔拆点,对于发射塔i他所拆出的第j个点就表示第j次发射,然后再看时间允不允许飞到目标进行连边。

然后二分图最大匹配之,看是否可行。

【ZOJ3461】

题目大意:每个人有一个钱数(有正有负),保证所有人的钱数之和为0。接下来给定m条带权无向边,如果这条边一旦启用,那么就要付上面的费用。最后问最少用多少费用可以使得这些人能够分钱分到每个人身上的钱数都为0。

人数<=16。边数可以接近完全图。

算法分析

……比赛时一直把他当有向边,然后果断悲剧。做法就是枚举每一个权和为0的子集,然后作最小生成树。然后再dp枚举子集合并之。

>_<其实这个做法是很显然的哎。后面dp枚举子集合并的复杂度是C(n,1)*2^1+ C(n,2)*2^2 + C(n,3)*2^3 + ... + C(n,n)*2^16<=2097120,所以不会超时。另外此题后面dp直接用2^16 * 2^16判子集的方法合并也不会超时……因为数据好像没有全0的情况。

【ZOJ3462】

题目大意:给定n(n<=1024)个文件,每个文件有几个Tags和一个大小。然后有m(m<=8192)个询问,每个询问给出一些Tags,如果一个询问中的Tags是某个文件的Tags的子集,那么将这个文件的算进符合这个询问,最后输出对于每个询问,符合条件的文件大小之和是多少。

算法分析

本题我的复杂度很不靠谱,理论上根本过不了……= =,不知道是否有正解。

就是对于所有文件的Tags建一棵Tire树,然后每个Tags建立一个邻接表,表示包含这个Tags的文件有哪些。

然后对于一个询问,就把这些Tags对应的文件搞出来求个交……当然这里有优化,如果某个文件在前面处理到的某个Tags里没有出现,那么后面就不用再枚举它了。接着就这样就过掉了……

【ZOJ3463】

题目描述十分不靠谱。他说一只手可以弹9个键,我和lcc都认为是5个白键,4个黑键……,谁知道他根本忽略了黑键。

算法

很简单的dp。F[i,j,k]表示左手拇指在i,右手拇指在j,弹完第k个音符需要的最小费用,然后暴力转移。

计算量是:52*52*1000*16 (16是转移复杂度)

【ZOJ3464】

水题,尽量让速度快的接球就可以了。

【ZOJ3465】

体力模拟题。

【ZOJ3466】

插头dp,基本概念就看cdq的ppt吧。

这个题不需要判断连通性,所以接进这个点的插头只需要计算数量,而这个点可引申出去的插头也只需要记录是哪几个,这样就可以拓展了。特别地,边界要处理一下。然后这个题目比较恶心的地方就是轮廓线会变。所以要分奇列和偶列讨论。

对于图中红色的插头,由于比较特殊,我就多弄了两位专门用来存……然后就是2进制储存是否有插头伸出来,hash便行。

 

【CODE】

【3457 打表的……】https://ideone.com/GQd73

【3458】https://ideone.com/JjnTV

【3459】https://ideone.com/SUwZr

【3460】https://ideone.com/1OUbx

【3461】https://ideone.com/YD6rA

【3462】https://ideone.com/OAzw8

【3463】https://ideone.com/BdF0V

【3464】https://ideone.com/Xa2go

【3465】https://ideone.com/c4Boa

 【3466】https://ideone.com/gORz0    (注意代码地址,ORz !!)

update@2011/2/12

2010年ACM-ICPC暑期集训报名【就是上一年……】

http://acm.zju.edu.cn/summer2010.htm

今年ACM-ICPC集训选拔报名在五月末截止,利用六月的月赛和选拔赛(根据报名人数,可能要求去现场比赛)选拔出20-30名学生参加正式暑期集训。

请欲参加集训的同学于5月30日22:00前发邮件到,邮件标题必须为“暑期集训报名”并填写以下表格(请以表格格式发送以方便登记):

  – 姓名
  – 性别
  – ZOJ ID
  – ZOJ Forum ID
  – TopCoder Handle(Optional)
  – 88 ID
  – 手机
  – 短号
  – E-mail
  – 学号
  – 专业
  – 所在校区
  – 校赛英文队名 

请勿使用 @st.zju.edu.cn或@grs.zju.edu.cn的邮箱(无法接受外网邮件),没有ZOJ Forum ID的也请马上注册一个。

收到邮件后将于24小时内回复确认,请注意查收。

选拔标准:

ZOJ题数:

  ZOJ总AC数300以上            100分 
  ZOJ总AC数240-299            80分 
  ZOJ总AC数180-239            60分 
  ZOJ总AC数120-179            40分 
  ZOJ总AC数 60-119            20分 
  ZOJ任选1个Volume AC满30题    20分 
  ZOJ任选2个Volume AC满60题    40分 
  ZOJ任选3个Volume AC满90题    60分 
  ZOJ任选4个Volume AC满120题   80分 
  ZOJ任选5个Volume AC满150题  100分 

校赛现场赛:

  前5名    50分 
  6-10名   40分 
  11-15名  30分 
  16-20名  20分 

省赛同步赛:(在赛前报名才有效,排名为报名人员内部排名)

  前3名    40分 
  4-6名    30分 
  7-9名    20分 
  10-12名  10分 

5月monthly:(在赛前报名才有效,排名为报名人员内部排名)

  前3名    40分 
  4-6名    30分 
  7-9名    20分 
  10-12名  10分 

TopCoder:
TopCoder Algorithm Rated Events不小于5次,且Rating History里第五高Rating为:

  2000以上  100分 
  1800-1999  80分 
  1600-1799  60分 
  1400-1599  40分
  1200-1399  20分 

以上每组只能选一项,合计得分男生100分/女生80分即可参加6月新手选拔。

注:
  *上一届校队成员自愿报名,并可不用参加选拔直接进入正式集训。
  *虽然报名截止时间为5月30日,但只有在ZOJ Monthly和省赛同步赛开始之前报名的才记该场成绩。
  *校赛的成绩对队伍中的三个人均有效。
  *只有第一次本科入学在06年及以后的同学有可能最后入选集训队,但是我们同时也欢迎06级以前的同学参加集训。
  *有其他特殊情况,认为自己可以不仅限于以上几组的同学可以在报名时询问。
  *报名同学要在报名后经常查邮箱,保证及时收到我们的各项临时通知。

TopCoder SRM 496

本次Rating降至空心黄

500搞了半天j打成i看不出来。。。交的时候都只剩200+分了。

最后500还是挂掉了,后来发现if里有个东西又打错了。。。一改Y了。

5555555555555555,现在神马都不行了。

在TC里那个字体太疼了= =。下次在外面打算了。

250

题目给定一个矩阵,每一笔你可以横向涂一笔连续的红的,或者竖向涂一笔连续的蓝的。如果一个格子被涂了红和蓝的,那么会变绿的。最后给出矩阵每个格子的颜色,问最少涂多少笔涂成这个样。

矩阵最大是50*50的。

……就是枚举。

class ColoredStrokes {
    vector    int m,n,ans;
    int v[55][55];
public:
    void solvex(){
      memset(v,0,sizeof(v));
      for (int i=0;i        for (int j=0;j          if ( (S[i][j]==’G’ || S[i][j]==’R’) && (!v[i][j]) ){
            for (int k=j;k              v[i][k]=1;
            ans++;
          }       
        }
    }
    
    void solvey(){
      memset(v,0,sizeof(v));
      for (int i=0;i        for (int j=0;j          if ( (S[i][j]==’B’ || S[i][j]==’G’) && (!v[i][j]) ){
            for (int k=i;k              v[k][j]=1;
            ans++;
          }
        }
    }
    
    int getLeast(vector       S=picture.begin();
      m=picture.size();
      n=picture[0].size();
      ans=0;
      solvex();
      solvey();
      return ans;
    }
};

 

500

有一些球在数轴上跑,然后他们都有一个相同的正的速度。(并且球不会发生碰撞)

然后他给出的第一个数组给定了一开始每个球的位置。

他又给了第二个数组,表示的是之后某个时刻每个球的位置。(但是有一些无关的球会被加进去)

假设way[i]表示第一个数组中第i个球是第二个数组中第way[i]个球,那么问way这个数组有多少种可能的不同的取值。

两个数组中的元素个数都<=50,题目保证了两个数组中,都不会有重复的数值。

样例:


具体做法就是先枚举他们的速度,设为dis。(显然速度只能是 abs(a[i]-b[j]) )

接下来我们来建边:

a[i] ->  (a[i]-dis) in b[j]

a[i] ->  (a[i]+dis) in b[j]

对于a[i],如果不存在其它的a[j]和它争b数组中的结点,那么显然他连出去多少条边,就有多少种方案,然后利用乘法原理乘起来就行。

然后我们关注发生冲突的。因为a,b数组中都不包含重复元素,那么发生冲突只能是这样情况:

a[i]+dis=a[j]-dis

然后继续发生冲突:a[j]+dis=a[k]-dis…

如此下去就会变成一条链。

然后……就判一个每个结点-dis和+dis的是否在b数组中存在。然后匹配时对于这条链,要么全-dis,要么全+dis,要么从中间部分开始,前一半-dis,后一半+dis……于是就这样每条链分开讨论,乘法原理将方案数乘起来。

然后再根据加法原理把不同速度的方案加起来。得到解。

class OneDimensionalBalls {
public:
    int up[55];
    int down[55];
    int m,n;
    int a[55];
    int b[55];
    int v[55];
    int tail;
    int dis;
    int List[55*55];
    
    void make_up_down(){
      int i,j;
      memset(up,0,sizeof(up));
      memset(down,0,sizeof(down));
      for (i=0;i        for (j=0;j          if (a[i]-dis==b[j]) up[i]=1;
          if (a[i]+dis==b[j]) down[i]=1;
        }
    }
    
    int Q[55];
    int Qt;
    int Link(int st){
      int i;
      Qt=1; Q[1]=st;
      v[st]=1;
      for (i=st+1;i        if (a[i]-a[Q[Qt]]==2*dis && down[Q[Qt]]){
          v[i]=1;
          Q[++Qt]=i;
        }
      int ed=Q[Qt];
      if (!up[st] && !down[ed]) return 0;
      if (!up[st]) return 1;
      if (!down[ed]) return 1;
      return Qt+1;
    }
    
    long long countValidGuesses(vector       m=firstPicture.size();
      n=secondPicture.size();
      for (int i=0;i      for (int i=0;i      sort(a,a+m);
      sort(b,b+n);
      tail=0;
      for (int i=0;i        for (int j=0;j          if (a[i]!=b[j])
            List[++tail]=abs(a[i]-b[j]);
      long long ans=0;
      long long now;
      sort(List+1,List+tail+1);
      for (int i=1;i<=tail;i++)
        if (i==1 || List[i]!=List[i-1]){
          dis=List[i];
          make_up_down();
          memset(v,0,sizeof(v));
          now=1;
          for (int j=0;j            if (!v[j])
              now*=Link(j);
          ans+=now;
        }
      return ans;
    }
};

 

950

推荐hhanger大神的解题报告

【AC_LCC_CWJ 第四场】Algorithmic Engagements 2009 & 【第一把SRM】

【AC_LCC_CWJ】

 本场纯打酱油……

就切了J题这个线段树。

http://acm.hust.edu.cn:8080/judge/contest/viewProblem.action?pid=22200

【题目大意】

给一个A[1..n],问是否存在1~n的一个排列,满足所有p[i]<=A[i]。然后后面还有m次修改,每次修改某个位置的A[i]的值。

n,m<=200000     1<=A[i]<=n

【算法分析】

……令Sum[k]表示数组A[i]里包含多少个<=k的数字。然后这个判定性问题转化为是否所有Sum[k]<=k。

然后就用线段树维护所有Sum[k]里,Max(Sum[k]-k)是不是小于等于0,如果是就满足,否则不满足。

【其它】

还想了好一会儿,真是太弱了。

【CODE】

http://xiudaima.appspot.com/code/detail/4489019

哎,弱得一塌糊涂……神马都弱

========================================================================================================

然后是昨天晚上的第一把SRM。

Orz,一进去就见到WJMZBMR和zbwmqlw!!!

WJMZBMR还被人用中文膜拜……

然后看到很多熟悉的ID,像swgr,RoBa之类的…

膜拜完以后开始比赛,显然第一把必须DIV2。

250神马二叉算法都能秒,直接暴力枚举。然后编译了半天不成功,都不知道干神马……

弄了好久,发现语言选了JAVA

接着打开500,据说就是DIV1的275。

觉得就是左边扫一遍右边扫一遍,得到每个位置的上限和下限,于是直接枚举。复杂度就是O(N√N + M)。

Orz表示1000^2 * 50毫无压力的神犇们!!!原来TC的精髓就是暴力……

搞完以后看到最后一题瞬间被秒。。。最后没有交1000。

其实当时的想法很接近正解,也是求连通块,就是没想出每个连通块有n!/2种方案。

好像DIV2里面也没有多少个交1000的……居然搞了DIV2里面第6,Rating一下变到1700+,然后名字就变成黄色了。。。

今天听说别人TC都用插件,下了个KawigiEdit,导入了以后再里面点Run Test Case显示神马g++不行之类的,鸭梨山大。改天再搞一搞。

刚在调这个KawigiEdit的时候被zbwmqlw神牛喊了一声没有听到Orz~罪过罪过