• 【poj3358】消因子+BSGS 或 消因子+欧拉定理 两种方法


    题意:给你一个分数,求它在二进制下的循环节的长度,还有第一个循环节从哪一位开始。

    For example, x = 1/10 = 0.0001100110011(00110011)w and 0001100110011 is a preperiod and 00110011 is a period of 1/10.

    思路一:

    我们可以观察一下1/10这组数据,按照二进制转换法(乘二法),我们可以得到:
    1/10  2/10 4/10 8/10 16/10 32/10 ...
    然后都分子都尽可能减去10,得到:
    1/10  2/10 4/10 8/10 6/10 2/10 ...
    这时候,发现出现了重复,那么这个重复就是我们要求的最小循环。
    抽象出模型如下:对p/q
    首先p'=p/gcd(p,q)
    q'=q/gcd(p,q);
    
    然后我们就是求p'*2^i == p'*2^j (mod q')   (“==”表示同余,i<j)
    经过变换得到:
    p'*2^i*(2^(j-i)-1) ==0 (mod q')
    也就是 q' | p'*2^i*(2^(j-i)-1)
    由于gcd(p',q')=1,
    得到: q' | 2^i*(2^(j-i)-1)
    因为2^(j-i)-1为奇数,所以q'有多少个2的幂,i就是多少,而且i就是循环开始位置的前一位。
    那么令q''为q'除去2的幂之后的数
    此时 q'' | 2^(j-i)-1
    也就是求出x,使得 2^x ==1 (mod q'')

    就是求p*(2^i) == p*(2^j) (mod q),除过来就是2^(i-j)==1(mod q)

    思路二:转自http://www.cnblogs.com/Konjakmoyu/p/5183339.html

    实现方法:

    方法一: 直接BSGS

    求2^x==1(mod n),就先消因子,然后在BSGS求解。

    过程中如果b%d!=0,那就说明在x>=T时无解。

    方法二:欧拉定理

    先消因子,则2与n互质。

    求2^x==1(mod n),根据欧拉定理2^phi(n)==1(%n),然后找phi(n)的质因子k。

    从小到大枚举质因子k,判断2^k==1(%n)则的得到答案。

    代码

    BSGS的:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 
     9 typedef long long LL;
    10 const LL N=40000;
    11 LL pl,bl;
    12 LL p[N];
    13 bool vis[N];
    14 struct node{
    15     LL d,id;
    16 }bit[N];
    17 
    18 bool cmp(node x,node y){
    19     if(x.d==y.d) return x.id<y.id;
    20     return x.d<y.d;
    21 }
    22 
    23 LL exgcd(LL a,LL b,LL &x,LL &y)
    24 {
    25     if(b==0) {x=1,y=0;return a;}
    26     LL tx,ty;
    27     LL d=exgcd(b,a%b,tx,ty);
    28     x=ty;y=tx-(a/b)*ty;
    29     return d;
    30 }
    31 
    32 LL find(LL x)
    33 {
    34     int l=1,r=bl;
    35     while(l<=r)
    36     {
    37         int mid=(l+r)>>1;
    38         if(bit[mid].d==x) return bit[mid].id;
    39         if(bit[mid].d<x) l=mid+1;
    40         if(bit[mid].d>x) r=mid-1;
    41     }
    42     return -1;
    43 }
    44 
    45 void exBSGS(LL b,LL &xx,LL &yy)
    46 {
    47     LL t,m,g,x,y,pm,am;
    48     while(b%2==0) {b/=2;xx++;}
    49     t=2;
    50     for(int i=1;i<=100;i++)
    51     {
    52         if(t%b==1) {yy=i;return ;}
    53         t=t*2%b;
    54     }
    55     m=(LL)(ceil((double)sqrt((double)b)));
    56     pm=1%b;bit[0].d=1%b;bit[0].id=0;
    57     for(int i=1;i<=m;i++)
    58     {
    59         bit[i].d=bit[i-1].d*2%b;
    60         bit[i].id=i;
    61         pm=pm*2%b;
    62     }
    63     sort(bit+1,bit+1+m,cmp);
    64     bl=1;
    65     for(int i=2;i<=m;i++)
    66     {
    67         if(bit[i].d!=bit[bl].d) bit[++bl]=bit[i];
    68     }
    69     exgcd(pm,b,x,y);
    70     am=x%b+b;
    71     t=1%b;
    72     for(int i=0;i<=m;i++)
    73     {
    74         x=find(t);
    75         if(x!=-1) {yy=i*m+x;return ;}
    76         t=t*am%b;
    77     }
    78     return ;
    79 }
    80 
    81 int main()
    82 {
    83     freopen("a.in","r",stdin);
    84     freopen("b.out","w",stdout);
    85     LL T=0,a,b;
    86     char c;
    87     while(scanf("%I64d%c%I64d",&a,&c,&b)!=EOF)
    88     {
    89         LL x,y;
    90         LL g=exgcd(a,b,x,y);
    91         a/=g,b/=g;
    92         x=1,y=-1;
    93         exBSGS(b,x,y);
    94         printf("Case #%I64d: %I64d,%I64d 
    ",++T,x,y);
    95     }
    96     return 0;
    97 }

     欧拉定理的:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const LL Max=(LL)1e6;
    const LL N=Max+100;
    LL fl;
    LL f[N];
    
    LL gcd(LL a,LL b)
    {
        if(b==0) return a;
        return gcd(b,a%b);
    }
    
    bool cmp(int x,int y){return x<y;}
    
    LL eular(LL x)
    {
        LL ans=x;
        for(int i=2;i*i<=x;i++)
        {
            if(x%i==0) ans/=i,ans=ans*(i-1);
            while(x%i==0) x/=i;
        }
        if(x>1) ans/=x,ans=ans*(x-1);
        return ans;
    }
    
    LL quickpow(LL a,LL b,LL mod)
    {
        LL ans=1%mod;
        while(b)
        {
            if(b&1) ans=ans*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return ans;
    }
    
    void solve(LL b,LL &xx,LL &yy)
    {
        LL k=2,x=b,ans=x;
        while(b%2==0) xx++,b/=2;
        LL phi=eular(b);
        for(int i=1;i*i<=phi;i++)
        {
            if(phi%i==0) f[++fl]=i,f[++fl]=phi/i;
        }
        sort(f+1,f+1+fl,cmp);
        for(int i=1;i<=fl;i++)
        {
            if(quickpow(2,f[i],b)==1) {yy=f[i];return ;}
        }
    }
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        LL T=0,a,b;
        char c;
        while(scanf("%I64d%c%I64d",&a,&c,&b)!=EOF)
        {
            LL x=1,y=0;
            LL g=gcd(a,b);
            a/=g,b/=g;
            solve(b,x,y);
            printf("Case #%I64d: %I64d,%I64d 
    ",++T,x,y);
        }
        return 0;
    }
  • 相关阅读:
    CUDA Error
    yolo v3 loss=nan, Avg loss=nan的一种原因
    C++ LinearRegression代码实现
    C++ 常用数学运算(加减乘除)代码实现 Utils.h, Utils.cpp(有疑问欢迎留言)
    C++ 彩色图像(RGB)三通道直方图计算和绘制,图像逆时针旋转90° 实现代码
    Leetcode 1005. Maximize Sum Of Array After K Negations
    Leetcode 1006. Clumsy Factorial
    Leetcode 617. Merge Two Binary Trees
    Leetcode 477. Total Hamming Distance
    python进制转换
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5611523.html
Copyright © 2020-2023  润新知