zoukankan      html  css  js  c++  java
  • 【BZOJ 1409】 Password 数论(扩展欧拉+矩阵快速幂+快速幂)

    读了一下题就会很愉快的发现,这个数列是关于p的幂次的斐波那契数列,很愉快,然后就很愉快的发现可以矩阵快速幂一波,然后再一看数据范围就......然后由于上帝与集合对我的正确启示,我就发现这个东西可以用欧拉函数降一下幂,因为两个数一定互质因此不用再加一个phi(m),于是放心的乘吧宝贝!!

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #define r register
    using namespace std;
    typedef long long LL;
    inline LL read()
    {
      r LL sum=0;
      r char ch=getchar();
      while(ch<'0'||ch>'9')ch=getchar();
      while(ch>='0'&&ch<='9')
      {
        sum=(sum<<1)+(sum<<3)+ch-'0';
        ch=getchar();
      }
      return sum;
    }
    LL prime[600000];
    bool isnot[600000];
    LL T;
    LL temp_a[4][4],a[4][4],b[4],temp_b[4];
    LL m,p;
    inline void Init()
    {
      for(r LL i=2;i<=(1<<16);i++)
      {
        if(!isnot[i])
          prime[++T]=i;
        for(r LL j=1;j<=T&&prime[j]*i<=(1<<17);j++)
        {
          isnot[prime[j]*i]=1;
          if(i%prime[j]==0)break;
        }
      }
      m=read(),p=read();
    }
    inline LL Opha(LL x)
    {
      r LL to=(LL)sqrt(x+0.5);
      r LL ans=x;
      for(r LL i=1;prime[i]<=to;i++)
      if(x%prime[i]==0)
      {
        ans=ans/prime[i]*(prime[i]-1);
        while(x%prime[i]==0)x/=prime[i];
      }
      if(x!=1)
        ans=ans/x*(x-1);
      return ans;
    }
    inline void Multi_One(LL k)
    {
      memset(temp_b,0,sizeof(temp_b));
      for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
          temp_b[i]=(temp_b[i]+a[i][j]*b[j]%k)%k;
      memcpy(b,temp_b,sizeof(b));
    }
    inline void Multi_Two(LL K)
    {
      memset(temp_a,0,sizeof(temp_a));
      for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
          for(int k=1;k<=2;k++)
            temp_a[i][j]=(temp_a[i][j]+a[i][k]*a[k][j]%K)%K;
      memcpy(a,temp_a,sizeof(a));
    }
    inline LL POW(LL x,LL k)
    {
      a[1][1]=1%k,a[1][2]=1%k,a[2][1]=1%k,a[2][2]=0;
      b[1]=1%k,b[2]=0;
      while(x)
      {
        if(x&1)Multi_One(k);
        x>>=1,Multi_Two(k);
      }
      b[1]%=k;
      return b[1];
    }
    inline LL Pow(LL x,LL y,LL k)
    {
      LL ans=1%k;
      while(y)
      {
        if(y&1)ans=ans*x%k;
        y>>=1,x=x*x%k;
      }
      ans%=k;
      return ans;
    }
    inline void Work()
    {
      while(m--)
      {
        r LL n=read(),q=read();
        r LL x=Opha(q);
        r LL y=POW(n-1,x);
        printf("%lld
    ",Pow(p,y,q));
      }
    }
    int main()
    {
      Init();
      Work();
      return 0;
    }
  • 相关阅读:
    .net framework 3.5 beta 2 / vs 2008 beta 2 有问题!
    提交了 VS 2008 sp1 对 Linq to SQL 的 xml 字段类型支持的一个 bug
    如何在 vista 的 iis 7 上面配置 asp.net 1.1 开发环境
    Linq to sql 中如何进行 left join
    Silverlight 2 beta 2 中目前不支持共享 WCF 的客户端类型
    Scott Guthrie 写的 Silverlight 教程索引
    利用 Xml Literal 功能复制一段 Xml
    Silverlight 2 beta 2 bug 解决办法 (持续更新中)
    C++使用内存映射文件入门
    如何在C++项目中引用Lib文件(VS2005)
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7260414.html
Copyright © 2011-2022 走看看