zoukankan      html  css  js  c++  java
  • LuoguP4861 按钮

    传送门
    这题一眼看上去要解(k^x equiv 1(mod m))的最小正整数解。
    于是我打了一个扩展BSGS
    这题这样做算的答案一直是0的。不过有另一个定理欧拉定理,(k^{varphi(m)} equiv 1 (mod m))
    首先我们要保证(gcd(k,m) = 1),如果不互质的话那就是无解的。
    因为有这样一句话:(k^x mod m)的结果必然是(gcd(k,m))的倍数。我有一些奇怪的理解方法。因为其实这两者都可以看成是(gcd(k,m))的t倍和(gcd(k,m))的p倍。两个(gcd(k,m))的正整数倍互相取模,那答案一定是(gcd(k,m))的倍数了。
    于是我们把(varphi(m))算了出来。但是这不一定是最小的解。
    我们可以证明最小的解必然是(varphi(m))的一个因子。反证法如下:
    假设(n mid varphi(m)),且n是满足(k^x equiv 1 (mod m))的最小正整数。那么因为(n mid varphi(m)),我们可以假设(pn < varphi(m) < p(n+1)),那么就有(k^{varphi(m)-pn} equiv 1 (mod m)),所以n并不是最小正整数解。
    所以我们枚举(varphi(m)) 的因子,符合条件且最小的就是答案。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define fr friend inline
    #define y1 poj
    #define mp make_pair
    #define pr pair<int,int>
    #define fi first
    #define sc second
    #define pb push_back
    
    using namespace std;
    typedef long long ll;
    const int M = 500005;
    const int mod = 999979;
    const int INF = 1000000009;
    const double eps = 1e-7;
    
    int read()
    {
       int ans = 0,op = 1;char ch = getchar();
       while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
       while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
       return ans * op;
    }
    
    int k,m,p[M],tot,cnt,ans[M];
    bool np[M];
    int gcd(int a,int b){return (!b)? a : gcd(b,a%b);}
    int mul(int a,int b,int t){return 1ll * a * b % t;}
    int qpow(int a,int b,int t)
    {
       int p = 1;
       while(b)
       {
          if(b & 1) p = mul(p,a,t);
          a = mul(a,a,t),b >>= 1;
       }
       return p;
    }
    void euler()
    {
       rep(i,2,M-2)
       {
          if(!np[i]) p[++tot] = i;
          for(int j = 1;i * p[j] <= M-2;j++)
          {
         np[i * p[j]] = 1;
         if(!(i % p[j])) break;
          }
       }
    }
    /*
    int phi(int x)
    {
       int res = 1;
       rep(i,1,tot)
       {
          bool flag = 1;
          while(!(x % p[i]))
          {
         x /= p[i];
         if(flag) res *= (p[i] - 1),flag = 0;
         else res *= p[i];
          }
       }
       if(x > 1) res *= (x-1);
       return res;
    }
    */
    
    int phi(int x)
    {
       int res = x;
       rep(i,2,sqrt(x)) if(!(x % i)){res = res / i * (i-1);while(!(x%i)) x /= i;}
       if(x > 1) res = res / x * (x-1);
       return res;
    }
    
    int main()
    {
       euler();
       m = read(),k = read();
       if(gcd(m,k) != 1) printf("Let's go Blue Jays!
    ");
       else
       {
          int g = phi(m);
          rep(i,1,sqrt(g))
          {
         if(qpow(k,i,m) == 1) ans[++cnt] = i;
         if(qpow(k,g/i,m) == 1) ans[++cnt] = g / i;
          }
          sort(ans+1,ans+1+cnt);
          printf("%d
    ",ans[1]);
       }
       return 0;
    }
    
    
    
  • 相关阅读:
    Oracle的并发多版本 读一致性
    挖掘ADO.NET Entity框架的性能
    System.Linq扩张方法Where (Lambda表达式)
    LINQ与HQL (二)
    HQL查询中的几个函数
    LINQ 与 HQL (一)
    C# 3.0的新特性(一)
    共享锁 排他锁
    Psytopic测试
    这些地方才是真正值得去的
  • 原文地址:https://www.cnblogs.com/captain1/p/10376327.html
Copyright © 2011-2022 走看看