zoukankan      html  css  js  c++  java
  • 解题报告 疯狂的馒头

    【题目背景】

    猪仙:馒头,馒头,又大又白的馒头······

      话说猪仙最喜欢的食物就是馒头,但是他很不喜欢的颜色是白色,于是他买来了各种各样的果酱,给馒头们穿衣服······

    【题目描述】

      猪仙一共买来了N个馒头,他还买来了M种果酱,在用第i种果酱染色时,他会把第((i*p)+q) mod n +1 ((i*q)+p)mod n +1个馒头都涂成颜色i,每个馒头的颜色为它最后一次被染的颜色,没有被染过的馒头的颜色为0,现在猪仙想知道每个馒头最后的颜色,于是他找到了你,但你只有1s的时间解决这个问题因为他要花很长时间来吃馒头······

    【输入文件】

     连续的四个整数,分别表示M,N,P,Q

    【输出文件】

     N行,第i行为第i个馒头的颜色。

    【输入样例】

    4 3 2 4

    【输出样例】

    3

    2

    2

    0

    【数据范围】

    对于20%的数据 n<=1000 m<=10000

    对于40%的数据 n<=10000 m<=100000

    对于60%的数据 n<=50000 m<=500000

    对于80%的数据 n<=300000 m<=3000000

    对于100%的数据 n<=1000000 m<=10000000

    所有数据中保证m*p+q m*q+p 均小于maxlongint

    来源于NOI导刊

    本题,模拟 2 个点

            filldword(v+1,50,1) 可以过 3 个点(速度是 for 循环的 5 倍)。

    线段树过六个点。

    动态线段树加优化过八个点。

    但以上这两种代码直奔两百行,这里主要讲能过全点的并查集。

    首先,分析以上两种算法的不足之处:染色的复杂度,毫无疑问是 O(1) 的,时间主要浪费在了判断各个馒头是否染过色上。

    而用并查集进行判断时,它的查找是跳跃性的,速度自然会快很多。

    因为染色是每 n 个数一个循环,所以当 n 远大于 m 时,只需要求出每 n 个馒头的馒头颜色,循环输出即可,所以需要求得馒头的个数为 min(m,n)。

     

    {$M 100000000}
    program  bread(input,output);
    var
        f:array[1..1000000] of longint;
     x:array[1..1000000] of longint;
     m,n,p,q,head,tail:longint;
    procedure init;
    begin
       assign(input,'bread.in');reset(input);
       readln(n,m,p,q);
       close(input);
    end;
    function max(a,b:longint):longint;
    begin
       if a>b then
        exit(a);
       exit(b);
    end;
    function min(a,b:longint):longint;
    begin
       if a>b then
        exit(b);
       exit(a);
    end;
    function find(xx:longint):longint;   //路径压缩
    begin
       if x[xx]=0 then
        exit(xx);
       f[xx]:=find(f[xx]);
       exit(f[xx]);
    end;
    procedure main;
    var
        i:longint;
    begin
        fillchar(x,sizeof(x),0);
     for i:=1 to n do
      f[i]:=i+1;    //初始化
     for i:=m downto 1 do
     begin
      if i<=m-n then
        exit;
      head:=min((((i*p)+q)mod n)+1,(((i*q)+p)mod n)+1);
      tail:=max((((i*p)+q)mod n)+1,(((i*q)+p)mod n)+1);
      head:=find(head);
      while head<=tail do
      begin
       x[head]:=i;
       head:=find(head);
      end;   //每个馒头的颜色
     end;   
    end;
    procedure print;
    var
        i:longint;
    begin
        assign(output,'bread.out');rewrite(output);
        for i:=1 to n do
      writeln(x[i]);
     close(output);
    end;
    begin
       init;
       main;
       print;
    end.

  • 相关阅读:
    国王游戏【贪心+证明】
    简练软考知识点整理-项目沟通管理简介
    简练软考知识点整理-项目人力资源管理简介
    简练软考知识点整理-项目质量管理简介
    简练软考知识点整理-项目成本管理简介
    简练软考知识点整理-项目时间管理简介
    简练软考知识点-项目范围管理过程简介
    简练软考知识点整理-项目整合管理介绍
    简练软考知识点整理-边际效用递减法则
    简练软考知识点整理-ABC成本法和ABC分析图法
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2113792.html
Copyright © 2011-2022 走看看