zoukankan      html  css  js  c++  java
  • BZOJ1406[AHOI2007密码箱]

    http://www.lydsy.com/JudgeOnline/problem.php?id=1406

    Description
    在一次偶然的情况下,小可可得到了一个密码箱,听说里面藏着一份古代流传下来的藏宝图,只要能破解密码就能打开箱子,而箱子背面刻着的古代图标,就是对密码的提示。经过艰苦的破译,小可可发现,这些图标表示一个数以及这个数与密码的关系。假设这个数是n,密码为x,那么可以得到如下表述: 密码x大于等于0,且小于n,而x的平方除以n,得到的余数为1。 小可可知道满足上述条件的x可能不止一个,所以一定要把所有满足条件的x计算出来,密码肯定就在其中。计算的过程是很艰苦的,你能否编写一个程序来帮助小可可呢?(题中x,n均为正整数)
    Input
    输入文件只有一行,且只有一个数字n(1<=n<=2,000,000,000)。
    Output
    你的程序需要找到所有满足前面所描述条件的x,如果不存在这样的x,你的程序只需输出一行“None”(引号不输出),否则请按照从小到大的顺序输出这些x,每行一个数。
    Sample Input
    12
    Sample Output
    1
    5
    7
    11

    显然O(N)是不行的。我们有:

    x^2≡1(mod n)

    x^2=kn+1

    x^2-1=kn

    (x-1)(x+1)=kn

    因为(x-1)(x+1)|n,则(x-1)(x+1)的约数一定是n的约数。我们可以先分解出n的约数t[i],再枚举j,使t[i]*j=x-1或x+1,再计算出(x+1)=t[i]*j+2或(x-1)=t[i]*j-2,验证是否符合(x-1)(x+1)|n,若符合,判重后加入答案表。最后排序后输出即可。

    有几个容易写挫的地方:1、几个变量要用int64 2、数组不要开小 3、计算(x-1)(x+1)时先分别对n取mod后乘,否则会溢出,此对判别乘积的mod无任何影响。

    program p1406;
    
    Var
     i,j,ct,top:longint;
     t,ans:array[0..60000] of int64;
     y,n:int64;
    
    procedure fopen;
      begin
      assign(input,'p1406.in');
      assign(output,'p1406.out');
      reset(input);
      rewrite(output);
    end;
    
    Procedure fclose;
      begin
      close(input);
      close(output);
    end;
    
    Function inset(P:int64):boolean;
    var
     i:longint;
      begin
      for i:=1 to top do
        if ans[i]=p then exit(true);
      exit(false);
    end;
    
    Procedure insert(P:int64);
      begin
      inc(top);
      ans[top]:=p;
    end;
    
      begin
      fopen;
      readln(n);ct:=0;
      fillchar(ans,sizeof(ans),0);
      fillchar(t,sizeof(t),0);
    
      for i:=1 to trunc(sqrt(n)) do
        if (n) mod i=0 then
          begin
          inc(ct);
          t[ct]:=i;
          if i*i<>n then
            begin
            inc(ct);
            t[ct]:=n div int64(i);
          end;
        end;
      
      top:=0;
      if n>1 then insert(1);
    
      for i:=1 to ct do
      if t[i]<n-1 then
        for j:=1 to round(sqrt(n))+10 div t[i] do
        if ((t[i]*j mod n)*((t[i]*j+2) mod n)) mod n=0 then
          if t[i]*j+1<n then
        
          if not inset(t[i]*j+1) then insert(t[i]*j+1);
       for i:=1 to ct do
        if t[i]>2 then
        for j:=1 to round(sqrt(n))+10 div t[i] do
        if ((t[i]*j mod n)*((t[i]*j-2) mod n)) mod n=0 then
        if (t[i]*j-1<n) and (t[i]*j-1>0) then
          if not inset(t[i]*j-1) then insert(t[i]*j-1);
     
      for i:=1 to top do
        for j:=i+1 to top do
          if ans[i]>ans[j] then
            begin
            y:=ans[i];
            ans[i]:=ans[j];
            ans[j]:=y;
          end;
      if top=0 then writeln('None');
        for i:=1 to top do
        writeln(ans[i]);
      fclose;
    end.
    
  • 相关阅读:
    e621. Activating a Keystroke When Any Child Component Has Focus
    e587. Filling Basic Shapes
    e591. Drawing Simple Text
    e595. Drawing an Image
    e586. Drawing Simple Shapes
    e636. Listening to All Key Events Before Delivery to Focused Component
    在 PL/SQL 块的哪部分可以对初始变量赋予新值? (选择1项)
    Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项)
    你判断下面语句,有什么作用?(单选)
    Oracle数据库表空间与数据文件的关系描述正确的是( )
  • 原文地址:https://www.cnblogs.com/htfy/p/2813448.html
Copyright © 2011-2022 走看看