• UVALive 4270 Discrete Square Roots


    题目描述:

      在已知一个离散平方根的情况下,按照从小到大的顺序输出其他所有的离散平方根。

      在模n意义下,非负整数x的离散平方根是满足0<=r<n且r2=x(mod n)的整数r。

    解题思路:

      假设要求的一个离散平方根为r1,则有:

        r2=x(mod n)

        r12=x(mod n)

      两式相减可得:

        r2-r12=0(mod n)

      即:

        r2-r12=kn

      令:

        a*b=n

      则有:

        r-r1=0(mod a)

        r+r1=0(mod b)

      即:

        r-r1=k1a

        r+r1=k2b

      两式相加可得:

        k1a+k2b=2r

      

      据此,枚举n的所有约数,得到所有可能的a和b。

      再利用扩展欧几里得算法解出所有的k2,代入r-r1=k1a即可得到r1

    代码在这:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef  long long ll;
     4 
     5 set<ll> ans;
     6  ll x,n,r;
     7 
     8 //扩展欧几里得算法
     9 void gcd(ll a,ll b,ll& d,ll& x,ll& y)
    10 {
    11     if(b==0)
    12     {
    13         d=a;
    14         x=1;
    15         y=0;
    16     }
    17     else
    18     {
    19         gcd(b,a%b,d,y,x);
    20         y-=x*(a/b);
    21     }
    22 }
    23 
    24 void solve(ll a,ll b)
    25 {
    26     ll k1,k2,d;
    27     gcd(a,b,d,k1,k2);
    28 
    29     if(2*r%d)
    30         return;
    31 
    32     k2*=(2*r/d);
    33 
    34     ll aa=a/d;
    35     k2%=aa;//k2是所有形如k2+k*aa的整数,最小的k2对应最小的r1
    36 
    37     ll r1=k2*b-r;
    38     while(r1<n)
    39     {
    40         if(r1>=0&&r1*r1%n==x)
    41             ans.insert(r1);
    42 
    43         r1+=aa*b;
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     int ca=0;
    50     while(~scanf("%lld%lld%lld",&x,&n,&r))
    51     {
    52         if(x==0&&n==0&&r==0)
    53             break;
    54 
    55         ans.clear();
    56 
    57         for(ll i=1;i*i<=n;i++)
    58             if(n%i==0)
    59             {
    60                  solve(i,n/i);
    61                  solve(n/i,i);
    62             }
    63 
    64 
    65         printf("Case %d: %lld",++ca,*ans.begin());
    66         for(set<ll>::iterator it=ans.begin();it!=ans.end();it++)
    67             if(it!=ans.begin())
    68             printf(" %lld",*it);
    69         printf("
    ");
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    分组与子报表Active Report6 使用(二)
    网站开发人员应该知道的62件事[转]
    如何恢复SVN中已删除文件或文件夹
    java中的List排序[转]
    [原]ActiveReport6 for net使用(一)
    Windows XP 不用输入密码自动登录
    IE不加载ActiveX控件的解决办法
    winRAR 打包小技巧
    iis负载均衡与文件同步[网摘]
    ASP.net的PDF打印(水晶报表)[摘]
  • 原文地址:https://www.cnblogs.com/from00/p/6574130.html
Copyright © 2020-2023  润新知