zoukankan      html  css  js  c++  java
  • bzoj3992

    题解:

    求模素数 p 原根的方法:对 p-1 进行素因子分解,记pi为p-1的第i个因子,若恒有a^((p-1)/pi) mod p ≠ 1  成立,则 a 就是 p 的原根。(对于合数求原根,只需把 p-1 换成 phi(p) 即可)

    首先比较暴力是f[i][j]表示前i个,乘积为j

    然后是n*m^2的

    我们可以利用原根将每个数变成g^x

    这样就变成了加和

    可以利用生成函数的思想

    然后分治+fft就可以了

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define rep(i,h,t) for(rint i=h;i<=t;i++)
    #define dep(i,t,h) for(rint i=t;i>=h;i--)
    #define IL inline
    const double pi=acos(-1.0);
    const int N=3e4;
    int n,m,l,r[N],a[N],b[N],w[N],c[N],g,kk,G=3;
    int p=1004535809;
    IL int fsp(int x,int y,int p)
    {
      int ans=1;
      while (y)
      {
        if(y&1) ans=1ll*ans*x%p;
        x=1ll*x*x%p;
        y>>=1;
      }
      return ans;
    }
    IL void jf(int &x,int y)
    {
      x+=y;
      if (x>p) x-=p;
    }
    IL void fft(int *a,int o)
    {
      rep(i,0,n-1) if (i>r[i]) swap(a[i],a[r[i]]);
      for (int i=1;i<n;i*=2)
      {
        int wn=fsp(G,(p-1)/(i*2),p); w[0]=1;
        rep(j,1,i-1) w[j]=(1ll*w[j-1]*wn)%p;
        for (int j=0;j<n;j+=(i*2))
        {
          int *x=a+j,*y=a+i+j;
          for (rint k=0;k<i;k++)
          {
            const int t=(1ll*w[k]*y[k])%p;
            y[k]=x[k]-t; if (y[k]<0) y[k]+=p;
            x[k]+=t; if (x[k]>p) x[k]-=p;
          }
        }
      }
      if (o==-1)
      {
        reverse(&a[1],&a[n]);
        for (int i=0,inv=fsp(n,p-2,p);i<n;i++)
          a[i]=1ll*a[i]*inv%p;
        rep(i,kk,m)
          jf(a[i%kk],a[i]),a[i]=0;
      }
    }
    IL void query()
    {
      l=0;
      for (n=1;n<=m;n<<=1) l++;
      rep(i,0,n-1) r[i]=(r[i/2]/2)|((i&1)<<(l-1));
      fft(a,1); fft(b,1);
      rep(i,0,n-1) a[i]=1ll*a[i]*b[i]%p;
      fft(a,-1);
    }
    IL void get_g(int x)
    {
      rep(i,1,x-1)
      {
        int j;
        for (j=1;j<m;j++)
          if (fsp(i,j,m)==1) break;
        if (j==m-1)
        {
          g=i; break;
        }
      }
    }
    struct re{
      int a[N];
    }now;
    re fsp2(int x)
    {
      if (x==1) return(now); 
      re tmp=fsp2(x/2);
      memcpy(b,tmp.a,sizeof(tmp.a));
      memcpy(a,tmp.a,sizeof(tmp.a));
      query();
      if (x%2)
      {
        memcpy(b,c,sizeof(c));
        query();
      }
      memcpy(tmp.a,a,sizeof(a));
      return(tmp);
    }
    int f[N];
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      int x,s;
      cin>>n>>m>>x>>s; kk=m-1;
      rep(i,1,s) cin>>a[i];
      get_g(m);
      rep(i,0,m-2) f[fsp(g,i,m)]=i;
      m*=2;
      rep(i,1,s) if (a[i]) now.a[f[a[i]]]++,c[f[a[i]]]++;
      fsp2(n);
      cout<<(a[f[x]]+p)%p;
      return 0;
    }
  • 相关阅读:
    tomcat安装
    卸载重安firefox
    Metasploit笔记之信息收集命令
    postgresql-9.0.18-1-linux.run启动
    ubuntu 安装自启动管理
    MySQL数据库”mysql SQL Error:1146,SQLState:42S02 “解决方法
    PE笔记之节表
    标准类型String(学习中)
    链表实现(打印元素的实现)
    C++中new和delete来创建和释放动态数组
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9420653.html
Copyright © 2011-2022 走看看