【Nov 10,哈希与并查集】模拟赛题解

      学习炜哥,最后再发代码。

 

No.1 distinct

 

  
    
【问题描述】
陶陶为了给一道平面几何题出数据,需要产生 N 个点(x[i],y[i])。已知 x,y 是由伪随机函
数顺序产生,即:
X[i
+ 1 ] = (X[i] * Ax + Bx + i) mod Cx (X[ 1 ], Ax,Bx,Cx 是事先给定的)
Y[i
+ 1 ] = (Y[i] * Ay + By + i) mod Cy (Y[ 1 ], Ay,By,Cy 是事先给定的)
这样,就可以快速连续产生很多点坐标(X[i], Y[i])。
不幸的是,这样产生的点有可能有相同的,虽然这种几率很少,但严谨的陶陶不允许这种事发生。
陶陶 要求你帮助他解决最少要产生前多少项时,正好有 N 个不相同的点。
【输入格式】
第一行。一个整数 N .
第二行:
4 个整数 X[ 1 ]、 Ax、Bx、Cx .
第三行:
4 个整数 Y[ 1 ]、 Ay、By、Cy .
【输出格式】
一个整数 M 。表示最少要连续产生 M 个点,正好有 N 个不相同的点。数据保证有答案。
【数据范围】
1 <= N <= 1 , 000 , 000 , 其它所有数据都在[ 1 ... 1 , 000 , 000 , 000 ]范围内。
【输入样例】
21
2 4 3 6
5 2 3 13
【输出样例】
24

 

很单纯的Hash。将求出的x与y分别成一个大质数,加起来模一个大质数即可。

 

No.2 Allbarns

 

  
    
【题目描述】
农民约翰打算建一个新的矩形谷仓。但是,矩形谷仓的
4 个角落不能在落在软土路基上,只能落在
一些固定点上。现在,他已经找到地面上有 N( 4 <= N <= 1 , 000 )个点,角落只可以落在这些点上。
他想知道依次每加多一个点,可以建立新谷仓的方法数量,请你帮助他找到答案。
【输入格式】
1 行:一个整数,N
2 行至 N + 1 行:每行有两个被空格分隔的整数的 x,y,作为一个点的坐标。所有的 x,y 
都不会 超过 16 , 000 。所有点都是不同的。
【输出格式】
共N行:每行表示当前可以建立的新的谷仓的数目。
【样例输入】
8
1 2
1 - 2
2 1
2 - 1
- 1 2
- 1 - 2
- 2 1
- 2 - 1
【样例输出】
0
0
0
0
0
1
3
6
【注释】
最后的答案是(
1 , 2 , 6 , 5 ),( 1 , 3 , 6 , 8 ),( 1 , 4 , 6 , 7 ),( 2 , 3 , 5 , 8 ),( 2 , 4 , 5 , 7 ), 
3 , 4 , 8 , 7

 

      还是哈希。对边进行hash,分别用边的中点横纵坐标和边长乘不同的大质数,再模一个大质数。由矩形性质,两条hash值相同的不同边即可构成一个矩形。

 

No.3 Cubes

 

  
    
【题目描述】
FJ 和 Best 用 N (
1 <= N <= 30 , 000 )块相同的小立方块玩游戏,小方块编号为 1 ..N。
开始时,小方块都单独分开的,每个看成一个柱子,即有N柱子。 FJ 要 Best 做P( 1 <= P <=  
  100 , 000 )个操作,操作有两种类型:
( 1 ) FJ 要求 Best 把X 号方块所在的柱子放到 Y 号所在的柱子上面,成一个新柱子。
(
2 )FJ 要求 Best 计算X 号方块所在柱子,它下面有多少个小方块。
请编个程序,帮助 Bet 计算。
【输入格式】
第一行:一个整数 P
2 ..P + 1 行:第 i + 1 行表示第 i 个 FJ 要求的合法操作。如果这行以 ' M ' 开头,
后面有两个整数 X,y 表示要进入( 1 )操作。 如果这行以 ' C ' 开头,后面有一个整数X,
表示要求计算 X 所在柱子下面的方块个数。
注:所有操作都是合法的。N 并没有出现在输入文件中。
【输出格式】
依次要求计算的值,每次一行。
【输入样例】
6 | 6 个操作
M
1 6 | 1 , 6 / 2 / 3 / 4 / 5 1 放在 6 上面。
C
1 | 输出: 1
M
2 4 | 1 , 6 / 2 , 4 / 3 / 5
M
2 6 | 2 , 4 , 1 , 6 / 3 / 5
C
3 | 输出 : 0
C
4 | 输出: 2
【输出样例】
1
0
2


      并查集。这道题和NOI2002年的银河英雄传说几乎相同…在这里不再赘述方法,网上很多。


 

No.4 friend

 

  
    
【问题描述】
有一个镇有 N 个居民。当然其中有许多人是朋友的关系。根据有名的谚语:“我朋友的朋
友也是我的朋友”,所以如果 A 和 B 是朋友,B 和 C 是朋友,那么 A 和 C 也是朋友。 你
的任务是算出在这个镇中最大的朋友集团为多少人。
【输入文件】
输入文件的第一行有
2 个正整数 N 和 M 。N 代表镇上居民的数目( 1 <= N <= 30000 ),
M 代表这些居民中朋友关系的数目( 0 <= M <= 30000 )。接下来的 M 行每行有 2 个整数 A,
B( 1 <= A,B <= N , A 不等于 B),代表 A,B 为朋友关系。这 M 行中可能有的会重复出
现。
【输出文件】
输出文件仅一行,在这个镇中最大的朋友集团为多少人。
【输入样例】
10 12
1 2
3 1
3 4
5 4
3 5
4 6
5 2
2 1
7 10
1 2
9 10
8 9
【输出样例】
6


      很纯粹的并查集。注意在计数前再压缩一下路径。


参考代码(distinct):

 

program distinct;

  var

    xx,yy:array[1..10000000]of longint;

    v:array[1..10000000]of boolean;

    num,x,y,i:int64;

    n,m:longint;

    q2,q1,a1,a2,b1,b2,c1,c2:longint;

  begin

    readln(n);

    readln(x,a1,b1,c1);

    readln(y,a2,b2,c2);

    m:=0;

    while m<n do

      begin

        inc(i);

        num:=(x*499979+y*299993)mod 9999991;

        while(v[num])and((xx[num]<>x)or(yy[num]<>y))do

          num:=(num+9871)mod 9999991;

        if not v[num]then

          begin

            yy[num]:=y;

            xx[num]:=x;

            v[num]:=true;

            inc(m);

          end;

        x:=(x*a1+b1+i)mod c1;

        y:=(y*a2+b2+i)mod c2;

      end;

    writeln(i);

  end.

 

参考代码(allbarns):

 

program allbarns;

  var

    x,y:longint;

    hash,len,xx,yy:array[1..4000037]of longint;

    nx,ny:array[1..4000037]of longint;

    n:integer;

    i,j:integer;

    h,l:int64;

    a,b,ans:longint;

  begin

    readln(n);

    for i:=1 to n do

      begin

        readln(nx[i],ny[i]);

        for j:=1 to i-1 do

          begin

            a:=(nx[i]+nx[j]);

            b:=(ny[i]+ny[j]);

            l:=sqr(nx[i]-nx[j])+sqr(ny[i]-ny[j]);

            h:=(abs(a*5869+b*3217+l*6529))mod 4000037;

            while(hash[h]<>0)and((len[h]<>l)or(xx[h]<>a)or(yy[h]<>b))do

              h:=(h+9871)mod 4000037;

            if hash[h]=0 then

              begin

                xx[h]:=a;

                yy[h]:=b;

                len[h]:=l;

                hash[h]:=1;

              end

              else begin

                     ans:=ans+hash[h];

                     inc(hash[h]);

                   end;

          end;

        writeln(ans);

      end;

  end.

 

参考代码(cubes):

 

program cubes;

  var

    before,count,f:array[1..30000]of integer;

    i,j,m,n,x,y,max:longint;

    c:char;

  function getfather(x:longint):longint;

    var

      fa:longint;

    begin

      if x=f[x] then exit(x);

      fa:=getfather(f[x]);

      before[x]:=before[x]+before[f[x]];

      f[x]:=fa;

      exit(f[x]);

    end;

  procedure union(x,y:longint);

    begin

      x:=getfather(x);

      y:=getfather(y);

      f[x]:=y;

      before[x]:=before[x]+count[y];

      count[y]:=count[x]+count[y];

    end;

  begin

    readln(n);

    for i:=1 to 30000 do

      begin

        f[i]:=i;

        before[i]:=0;

        count[i]:=1;

      end;

    for i:=1 to n do

      begin

        read(c);

        case c of

          'M':begin

                readln(x,y);

                if f[x]<>f[y] then

                  union(x,y);

              end;

          'C':begin

                readln(x);

                getfather(x);

                writeln(before[x]);

              end;

        end;

      end;

  end.

 

 

参考代码(friend):

 

program friend;

  var

    f:array[1..30000]of integer;

    i,j,m,n,x,y,max:longint;

    ans:array[1..30000]of integer;

  function getfather(x:longint):longint;

    begin

      if x=f[x] then exit(x);

      f[x]:=getfather(f[x]);

      exit(f[x]);

    end;

  procedure union(x,y:longint);

    begin

      x:=getfather(x);

      y:=getfather(y);

      if x<>y then f[x]:=y;

    end;

  begin

    readln(n,m);

    for i:=1 to n do

      f[i]:=i;

    for i:=1 to m do

      begin

        readln(x,y);

        if f[x]<>f[y] then

          union(x,y);

      end;

    for i:=1 to n do

      f[i]:=getfather(i);

    max:=0;

    for i:=1 to n do

      inc(ans[f[i]]);

    for i:=1 to n do

      if ans[i]>max then max:=ans[i];

    writeln(max);

  end.

 

 

 

本文地址:http://www.cnblogs.com/saltless/archive/2010/11/10/1874126.html

(saltless原创,转载请注明出处)

你可能感兴趣的:(并查集)