zoukankan      html  css  js  c++  java
  • jzoj C组 2017.1.21

    第一题——Sum the Square

    题目描述

    当你把一个正整数的各个数位平方之后相加,你会发现一些奇妙的现象,它出现了循环。比如说{5, 25, 29, 85, 89, 145, 42, 20, 4, 16, 37, 58, 89, …}。当然,说这个性质纯粹是为了好玩。为了多一些乐趣,这里给出两张图,这是两组平凡的数列:

    这里写图片描述

    现在,给定两个整数a1和b1,分别按照上述的方式构造数列{a1, a2, …, am}和{b1, b2, …, bn},其中am等于bn,你的目标是使得n+m最小。

    输入

    输入包含若干组数据,每组数据包含一行两个整数,分别为a1和b1。

    输入0 0表示结束。

    输出

    每组数据输出一行,包含:a1,空格,b1,空格,n+m。

    样例输入

    89 89

    19 100

    61 19

    0 0

    样例输出

    89 89 2

    19 100 5

    61 19 0

    数据范围限制

    【数据范围】 1<=A,B<=10^9

    测试数据少于2000组


    纯模拟,现将a的环求出来,然后再求B的环,如果当前b环的数也还A的环中,就判断该n+m是否比原来的小,则更新值。


    代码如下:

    var x,y,a,b,lx,ly,min:longint;
        fx,fy:array[0..1000]of longint;
    
    function sq(x:longint):longint;
    var  s:string;
         i:longint;
    begin
      s:='';
      str(x,s);
      sq:=0;
      for i:=1 to length(s) do sq:=sq+sqr(ord(s[i])-48);
    end;
    
    begin
      assign(input,'square.in');
      assign(output,'square.out');
      reset(input);
      rewrite(output);  
      while 0=0 do
        begin
          readln(x,y);
          a:=x; b:=y;
          min:=maxlongint;
          lx:=0;
          ly:=0;
          fillchar(fx,sizeof(fx),#0);
          fillchar(fy,sizeof(fy),#0);
          if (x=0)and(y=0) then exit;
          if x=y then
            begin
              writeln(x,' ',y,' ',2);
              continue;
            end;
          if x>729 then
            begin
              x:=sq(x);
              inc(lx);
            end;
          if y>729 then
            begin
              y:=sq(y);
              inc(ly);
            end;
          while fx[x]=0 do
            begin
              inc(lx);
              fx[x]:=lx;
              x:=sq(x);
            end;
          while fy[y]=0 do
            begin
              inc(ly);
              if (fx[y]+ly<min)and(fx[y]>0) then min:=fx[y]+ly;
              fy[y]:=sq(y);
              y:=sq(y);
            end;
          if min=maxlongint then writeln(a,' ',b,' ',0)
                            else writeln(a,' ',b,' ',min);
        end;
      close(input);
      close(output);
    end.

    第二题——TheNumberGame

    题目描述

    Alice和Bob在玩一个游戏。游戏开始时,他们被给定一个整数。两个人轮流进行操作,每次操作时,玩家可以选取当前整数T的任意一个因子x,不包括1和T。然后将T-x交给下一名玩家。不能操作的玩家输。Alice先手。Alice和Bob都积极的进行游戏。你希望知道对于某些整数,谁会赢得游戏。

    输入

    数据包括若干组,每组数据包含一行一个整数,表示游戏开始时的整数。

    输出

    每组数据输出一行,Alice或Bob,表示胜者。

    样例输入

    2

    3

    6

    样例输出

    Bob

    Bob

    Alice

    【样例说明】

    当初始整数为2和3时,Alice无法操作,故Bob获胜。

    当初始整数为6时,Alice可以选择3,使得Bob无法操作,故Alice胜。

    数据范围限制

    【数据范围】

    对于30%的数据,输入整数<=10^5,数据少于100组

    对于100%的数据,1<=输入整数<=10^18,数据少于1000组


    找规律:①如果整数为奇数,则Bob赢
    ②如果整数是2的奇数次方,则Bob赢
    ③如果都不满足上面的两种情况,则Alice赢


    代码如下:

    var   i:longint;
          n:qword;
          f:boolean;
          a:array[1..32]of qword;
    begin
      assign(input,'game.in');
      assign(output,'game.out');
      reset(input);
      rewrite(output);
      a[1]:=2;
      for i:=2 to 32 do a[i]:=a[i-1]*4;
      while not eoln do
        begin
          readln(n);
          f:=false;
          if n mod 2=1 then
            begin
              writeln('Bob');
            end
          else
            begin
              for i:=1 to 32 do
                if a[i]=n then begin writeln('Bob'); f:=true; break; end;
              if f=false then writeln('Alice');
            end;
        end;
      close(input);
      close(output);
    end.
    

    第三题——Mixing Chemicals

    题目描述

    实验室有n瓶化学药品,编号为0到n-1,你知道第i瓶只有和第c[i]瓶放在一起才会发生爆炸。为了整理实验室,你需要将他们装进k个不同的盒子里。显然,为了你的生命安全,你不能把两瓶会造成爆炸的药品放进同一个箱子。你希望计算出有多少中不同的方案。为了降低难度,你只需要将答案mod 1000000007。

    输入

    第一行一个整数T,表示有T组测试数据。

    对于每组数据

    第一行两个整数n,k

    第二行n个整数表示c[i]

    输出

    对于每组数据输出一行一个整数。

    样例输入

    3

    3 3

    1 2 0

    4 3

    1 2 0 0

    3 2

    1 2 0

    样例输出

    6

    12

    0

    数据范围限制

    【数据范围】

    1<=T<=50

    1<=n<=100

    2<=k<=1000

    0<=c i < n,i≠c[i]

    对于30%的数据T,n,k<=50


    终于将这鬼题AK了(多亏了林大犇)的指导。
    我们可以将不能放在一起的瓶子,看成两个点连成一条边(这样就形成了几个环套树也就是连通块),可以填k种颜色。
    然后我们求出每个点可以填涂的颜色的数量,设f[i,0/1]表示为第i个点,0为填除黑色外的颜色,1为填黑色。
    dp式为 f[i,0]:=(f[i-1,1]* (k-1)+f[i-1,0]*(k-2)) mod mo; f[i,1]:=f[i-1,0] mod mo;
    mo为要取摸的数
    然后我们将每个点在哪个环求出来,在求出连通块的个数,然后ans:=ans* (f[lt,1]*k mod mo)mod mo; lt为当前循环的搜到的连通块的个数
    最后 n:=n-z; for i:=1 to n do ans:=ans*(k-1) mod mo; writeln(ans); 求出将每个连通块的填颜色的个数相乘就求出ans,最后输出就好了。


    代码如下:

    const mo=1000000007;
    var   t,i,n,k,w,j:longint;
          lt,ans,temp,z:int64;
          f:array[0..100,0..1]of int64;
          a,b:array[0..100]of longint;
    begin
      assign(input,'mix.in');
      assign(output,'mix.out');
      reset(input);
      rewrite(output);
      readln(t);
      for j:=1 to t do
        begin
          fillchar(a,sizeof(a),#0);
          fillchar(b,sizeof(b),#0);
          readln(n,k);
          f[1,0]:=k-1;
          f[0,1]:=1;
          for i:=2 to n do
            begin
              f[i,0]:=(f[i-1,1]*(k-1)+f[i-1,0]*(k-2)) mod mo;
              f[i,1]:=f[i-1,0] mod mo;
            end;
          for i:=0 to n-1 do
            begin
              read(a[i]);
              b[i]:=233;
            end;
          z:=0;
          ans:=1;
          readln;
          for i:=0 to n-1 do
            if b[i]=233 then
              begin
                temp:=i;
                while b[temp]=233 do
                  begin
                    b[temp]:=i;
                    temp:=a[temp];
                  end;
                if b[temp]<>i then continue;
                lt:=0;
                w:=temp;
                repeat
                  inc(lt);
                  temp:=a[temp];
                until temp=w;
                ans:=ans*(f[lt,1]*k mod mo)mod mo;
                z:=z+lt;
              end;
          n:=n-z;
          for i:=1 to n do ans:=ans*(k-1) mod mo;
          writeln(ans);
        end;
      close(input);
      close(output);
    end.

    今天做提高模拟题,一大堆0分的人(当然也有我),正是欲哭无泪啊!
    感觉以我现在的水平,做两万年都做不出来(没有大神的指导),我还是先回松山湖修炼修炼吧。

  • 相关阅读:
    memcached 高级机制(一)
    memcached 简介
    Hibernate
    Linux中的搜索命令
    Linux的常用命令
    Git清除用户名和密码
    关于Git的简单使用
    文件的上传与下载(2)
    关于文件的上传和后台接收
    验证码的制作
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412441.html
Copyright © 2011-2022 走看看